Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the implementation principle of Provide and Inject in Vue3?

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces the relevant knowledge of the implementation principle of Provide and Inject in Vue3, the content is detailed and easy to understand, the operation is simple and fast, and it has a certain reference value. I believe you will gain something after reading this article on the implementation principle of Provide and Inject in Vue3. Let's take a look.

Knowledge Review of prototype and prototype chain

Prototype and _ _ proto__

Prototype is generally called an explicit prototype, and _ _ proto__ is generally referred to as an implicit prototype. After each function is created, by default, it has a property called prototype, which represents the prototype object of the function.

Prototype chain

When we access a property of a JS object, JS will first look in the properties defined by the object, and if it cannot find it, it will look up an object along the chain associated with the implicit prototype of the object's _ _ proto__, which is called the prototype chain.

Function Fn () {} Fn.prototype.name = 'coboy'let fn1 = new Fn () fn1.age = 18console.log (fn1.name) / / coboyconsole.log (fn1.age) / / 18

Fn1 is the instance object from the Fn function new, fn1.age is the property on the instance object, and fn1.name comes from the Fn.prototype prototype object, because the _ _ proto__ implicit prototype of fn1 is the prototype object Fn.prototype that points to the function Fn. In a sense, a prototype chain is to have one reference type inherit the properties and methods of another reference type.

Function Fn () {} Fn.prototype.name = 'coboy'let fn1 = new Fn () fn1.name =' cobyte'console.log (fn1.name) / / cobyte

When accessing the property name of the instance object fn1, JS will first look in the property of the instance object fn1. It just so happens that fn1 defines a name property, so it directly returns the value cobyte of its own property, otherwise it will continue to look up the Fn.prototype along the prototype chain, then coboy will be returned.

After reviewing the knowledge of prototypes and prototype chains, we began to explore the implementation principles of Provide/Inject.

Use Provide

When using provide in setup (), we first explicitly import the provide method from vue. This allows us to call provide to define each property.

The provide function allows you to define property with two parameters.

Name (type)

Value

Import {provide} from 'vue'export default {setup () {provide (' name', 'coboy')}} provide API implementation principle

So what is the principle of this provide API implementation?

The provide function can be reduced to

Export function provide (key Value) {/ / get the current component instance const currentInstance: any = getCurrentInstance () if (currentInstance) {/ / get the provides property on the current component instance let {provides} = currentInstance / / get the provides property of the current parent component const parentProvides = currentInstance.parent.provides / / if the current provides is the same as the parent provides, then not yet Assign if (provides = parentProvides) {/ / Object.create () es6 another way to create an object It can be understood as inheriting an object, and the attributes added are under the prototype. Provides = currentInstance.provides = Object.create (parentProvides)} provides [key] = value}}

To sum up, provide API stores the incoming data on the provides on the current component instance object by obtaining the current component instance object, and sets the provides property of the parent component to the prototype object of the provides property of the current component instance object through the new API Object.create of ES6.

Handling of provides property during initialization of component instance object

By looking at the source code of the instance object, we can see that there are two properties, parent and provides, on the instance component instance object. At initialization time, if there is a parent component, assign the provides of the parent component to the provides of the current component instance object, if not, create a new object, and set the provides property of the application context to the property on the prototype object of the new object.

Use Inject

When using inject in setup (), you also need to import explicitly from vue. Once imported, we can call it to define how the components are exposed to us.

The inject function takes two parameters:

The name of property to inject

Default value (optional)

Import {inject} from 'vue'export default {setup () {const name = inject (' name', 'cobyte') return {name}} inject API implementation principle

So what is the principle of this inject API implementation?

The inject function can be reduced to

Export function inject (key, defaultValue, treatDefaultAsFactory = false) {/ / get the current component instance object const instance = currentInstance | | currentRenderingInstance if (instance) {/ / if the intance is in the root directory, return to the provides of the appContext, otherwise return the provides const provides of the parent component = instance.parent = = null? Instance.vnode.appContext & & instance.vnode.appContext.provides: instance.parent.provides if (provides & & key in provides) {return provides [key]} else if (arguments.length > 1) {/ / if there is a parameter to return treatDefaultAsFactory & & isFunction (defaultValue) / / if the default content is a function's Execute and bind the proxy object of the component instance to the this of the function through the call method? DefaultValue.call (instance.proxy): defaultValue}

Through the inject source code analysis, we can know that inject first gets the instance object of the current component, and then determines whether the root component is the root component. If it is the root component, it returns to the provides of the appContext, otherwise it returns the provides of the parent component.

If the currently acquired key has a value on provides, the value is returned. If not, the default content is determined. If the default content is a function, it is executed and the proxy object of the component instance is bound to the this of the function through the call method, otherwise the default content is returned directly.

Summary of the principle of provide/inject implementation

Through the above analysis, we can know that the implementation principle of provide/inject is relatively simple, that is, it skillfully uses prototypes and prototype chains to inherit and obtain data. When provide API calls the setting, the parent provides is set as the property on the current provides object prototype object. When inject acquires the attribute value in the provides object, it first acquires the property of the provides object itself. If it cannot find it, it looks up the object along the prototype chain.

Extension: Object.create principle

Method description

The Object.create () method creates a new object and takes the first parameter of the method as the value of the _ _ proto__ property of the new object (using the first parameter as the prototype object for the constructor of the new object)

The Object.create () method has a second optional parameter, which is an object. Each property of the object is taken as its own property of the new object. The property value of the object appears in the form of descriptor (Object.getOwnPropertyDescriptor (obj, 'key')), and the attribute value defaults to false.

Source code simulation

Object.myCreate = function (proto, propertyObject = undefined) {if (propertyObject = null) {/ / it is not determined whether propertyObject is the original packaging object throw 'TypeError'} else {function Fn () {} / / set prototype object property Fn.prototype = proto const obj = new Fn () if (propertyObject! = undefined) {Object.defineProperties (obj) PropertyObject)} if (proto = null) {/ / create an object without a prototype object Object.create (null) obj.__proto__ = null} return obj}}

Define an empty constructor, then specify the prototype object of the constructor, create an empty object through the new operator, if you find that the second parameter is passed, set key and value for the created object through Object.defineProperties, and finally return the created object.

Example

/ / when the second parameter is null Throw TypeError// const throwErr = Object.myCreate ({name: 'coboy'}, null) / / Uncaught TypeError// to build a prototype object with const obj1 = Object.myCreate ({name:' coboy'}) console.log (obj1) / / {}, the prototype object of obj1's constructor is {name: 'coboy'} const obj2 = Object.myCreate ({name:' coboy'}, {age: {value: 18) Enumerable: true}}) console.log (obj2) / / {age: 18}, the prototype object of the constructor of obj2 is {name: 'coboy'} extension: two consecutive assignment expressions

Provides = currentInstance.provides = Object.create (parentProvides) what happened?

Object.create (parentProvides) creates a new object reference. If you just update currentInstance.provides to the new object reference, then the provides reference is still the old reference, so you need to update the provides reference to the new object reference at the same time.

Analysis from the authoritative Guide to JavaScript

JavaScript always evaluates expressions in strict order from left to right

Everything is an expression, everything is an operation.

Provides = currentInstance.provides = Object.create (parentProvides)

The provides above is an expression that is strictly called the left-hand (Ihs) Operand of the assignment expression. And the whole currentInstance.provides = Object.create (parentProvides) on the right is also treated as an expression. The whole assignment expression is assigned to the leftmost providescurrentInstance.provides = Object.create (parentProvides), which is also an assignment expression. Object.create (parentProvides) creates a new reference assignment to the provides attribute on the reference currentInstance.

The semantics of the expression currentInstance.provides are:

Evaluate the single-valued expression currentInstance to get a reference to currentInstance

Understand the name provides on the right as an identifier and as "." The right Operand of the operation

The result of evaluating a currentInstance.provides expression (Result)

CurrentInstance.provides when it is the left Operand of the assignment expression, it is an assigned reference, and when it is the right Operand, its value is evaluated.

Note: the Operand to the left of an assignment expression can be another expression, but it can never be an expression to the left of the equal sign in a declaration statement. For example, if the above is written as let provides = xxx, then at this time, provides is only a literal text that expresses the name and the static parsing period is understood as an identifier, not an expression.

This is the end of the article on "what is the implementation principle of Provide and Inject in Vue3". Thank you for reading! I believe you all have a certain understanding of the knowledge of "what is the principle of Provide and Inject in Vue3". If you want to learn more, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report