Let's talk about the implementation principles of Provide and Inject in Vue3
This article will give you an in-depth understanding of Vue3 and introduce the implementation principle of Provide / Inject in detail. I hope it will be helpful to everyone!
The implementation principle of Vue3's Provide/Inject is actually realized by clever use of prototypes and prototype chains, so before understanding the implementation principle of Vue3's Provide/Inject, we First review the knowledge of prototypes and prototype chains. [Related recommendations: vue.js video tutorial]
Knowledge review of prototype and prototype chain
- ##prototype and
- __proto__
__proto__ is generally called the implicit prototype. After each function is created, by default, it will have a property named prototype, which represents the prototype object of the function.
- Prototype chain
__proto__ The chain associated with this implicit prototype searches for the previous object. This chain is called the prototype chain.
function Fn() {} Fn.prototype.name = 'coboy' let fn1 = new Fn() fn1.age = 18 console.log(fn1.name) // coboy console.log(fn1.age) // 18fn1 is the instance object created by the Fn function new, fn1.age is the attribute on this instance object, and fn1.name comes from the Fn.prototype prototype object, because fn1’s
__proto__ The implicit prototype is the prototype object Fn.prototype pointing to the function Fn. A prototype chain allows one reference type to 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) // cobyteWhen accessing the attribute name of the instance object fn1, JS will first search in the attributes of the instance object fn1. It happens that fn1 defines a name attribute, so it directly returns the value cobyte of its own attribute. Otherwise, it will continue to look up Fn.prototype along the prototype chain, and then it will return to coboy. After reviewing the knowledge of prototypes and prototype chains, we began to explore the implementation principles of Provide/Inject.
Using Provide
When usingprovide in
setup(), we first start with
vue Explicitly import the
provide method. This allows us to call
provide to define each property.
provide The function allows you to define a property through two parameters
- ##name (
type)
value-
import { provide } from 'vue' export default { setup() { provide('name', 'coboy') } }
So what is the provide API implementation principle?
The provide function can be simplified to
export function provide(key, value) { // 获取当前组件实例 const currentInstance: any = getCurrentInstance() if(currentInstance) { // 获取当前组件实例上provides属性 let { provides } = currentInstance // 获取当前父级组件的provides属性 const parentProvides = currentInstance.parent.provides // 如果当前的provides和父级的provides相同则说明还没赋值 if(provides === parentProvides) { // Object.create() es6创建对象的另一种方式,可以理解为继承一个对象, 添加的属性是在原型下。 provides = currentInstance.provides = Object.create(parentProvides) } provides[key] = value } }
In summary, the provide API is to obtain the instance object of the current component and store the incoming data in the provides on the current component instance object. And through ES6's new API Object.create, the provides attribute of the parent component is set to the prototype object of the provides attribute of the current component instance object.
Processing of the provides attribute when the component instance object is initializedSource code location: runtime-core/src/component.ts
By looking at the source code of the instance object, we can see that there are two attributes, parent and provides, on the instance component instance object. During initialization, if a parent component exists, assign the parent component's provides to the current component instance object's provides. If not, create a new object, and set the application context's provides attribute to the attribute on the prototype object of the new object. .
When using
inject in setup()
, you also need to start from vue
Explicit import. After importing, we can call it to define the component mode exposed to us.
The function has two parameters:
- The name of the property to be injected
- Default Value (
- optional
)
import { inject } from 'vue' export default { setup() { const name = inject('name', 'cobyte') return { name } } }
So what is the implementation principle of this inject API?
inject function can be simplified to
export function inject( key, defaultValue, treatDefaultAsFactory = false ) { // 获取当前组件实例对象 const instance = currentInstance || currentRenderingInstance if (instance) { // 如果intance位于根目录下,则返回到appContext的provides,否则就返回父组件的provides const provides = 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) { // 如果存在1个参数以上 return treatDefaultAsFactory && isFunction(defaultValue) // 如果默认内容是个函数的,就执行并且通过call方法把组件实例的代理对象绑定到该函数的this上 ? defaultValue.call(instance.proxy) : defaultValue } } }
Through inject source code analysis, we can know that inject first obtains the instance object of the current component, and then determines whether it is the root component. If it is the root component, it returns to the appContext Provides, otherwise the provides of the parent component are returned.
If the currently obtained key has a value on provides, then return the value. If not, determine whether there is default content. If the default content is a function, execute it and use the call method to set the proxy object of the component instance. Bind to this function, otherwise the default content will be returned directly.
provide/inject实现原理总结
通过上面的分析,可以得知provide/inject实现原理还是比较简单的,就是巧妙地利用了原型和原型链进行数据的继承和获取。provide API调用设置的时候,设置父级的provides为当前provides对象原型对象上的属性,在inject获取provides对象中的属性值时,优先获取provides对象自身的属性,如果自身查找不到,则沿着原型链向上一个对象中去查找。
拓展:Object.create原理
方法说明
- Object.create()方法创建一个新的对象,并以方法的第一个参数作为新对象的
__proto__
属性的值(以第一个参数作为新对象的构造函数的原型对象) - Object.create()方法还有第二个可选参数,是一个对象,对象的每个属性都会作为新对象的自身属性,对象的属性值以descriptor(Object.getOwnPropertyDescriptor(obj, 'key'))的形式出现,且enumerable默认为false
源码模拟
Object.myCreate = function (proto, propertyObject = undefined) { if (propertyObject === null) { // 这里没有判断propertyObject是否是原始包装对象 throw 'TypeError' } else { function Fn () {} // 设置原型对象属性 Fn.prototype = proto const obj = new Fn() if (propertyObject !== undefined) { Object.defineProperties(obj, propertyObject) } if (proto === null) { // 创建一个没有原型对象的对象,Object.create(null) obj.__proto__ = null } return obj } }
定义一个空的构造函数,然后指定构造函数的原型对象,通过new运算符创建一个空对象,如果发现传递了第二个参数,通过Object.defineProperties为创建的对象设置key、value,最后返回创建的对象即可。
示例
// 第二个参数为null时,抛出TypeError // const throwErr = Object.myCreate({name: 'coboy'}, null) // Uncaught TypeError // 构建一个以 const obj1 = Object.myCreate({name: 'coboy'}) console.log(obj1) // {}, obj1的构造函数的原型对象是{name: 'coboy'} const obj2 = Object.myCreate({name: 'coboy'}, { age: { value: 18, enumerable: true } }) console.log(obj2) // {age: 18}, obj2的构造函数的原型对象是{name: 'coboy'}
拓展:两个连续赋值的表达式
provides = currentInstance.provides = Object.create(parentProvides)
发生了什么?
Object.create(parentProvides)
创建了一个新的对象引用,如果只是把 currentInstance.provides
更新为新的对象引用,那么provides
的引用还是旧的引用,所以需要同时把provides
的引用也更新为新的对象引用。
来自《JavaScript权威指南》的解析
- JavaScript总是严格按照从左至右的顺序来计算表达式
- 一切都是表达式,一切都是运算
provides = currentInstance.provides = Object.create(parentProvides)
上述的provides是一个表达式,它被严格地称为“赋值表达式的左手端(Ihs)操作数”。
而右侧 currentInstance.provides = Object.create(parentProvides)
这一个整体也当做一个表达式,这一个整体赋值表达式的计算结果是赋值给了最左侧的providescurrentInstance.provides = Object.create(parentProvides)
这个表达式同时也是一个赋值表达式,Object.create(parentProvides)创建了一个新的引用赋值给了currentInstance这个引用上的provides属性
currentInstance.provides
这个表达式的语义是:
- 计算单值表达式currentInstance,得到currentInstance的引用
- 将右侧的名字provides理解为一个标识符,并作为“.”运算的右操作数
- 计算
currentInstance.provides
表达式的结果(Result)
currentInstance.provides
当它作为赋值表达式的左操作数时,它是一个被赋值的引用,而当它作为右操作数时,则计算它的值。
注意:赋值表达式左侧的操作数可以是另一个表达式,而在声明语句中的等号左边,绝不可能是一个表达式。 例如上面的如果写成了let provides = xxx,那么这个时候,provides只是一个表达名字的、静态语法分析期作为标识符来理解的字面文本,而不是一个表达式。
(学习视频分享:web前端教程)
The above is the detailed content of Let's talk about the implementation principles of Provide and Inject in Vue3. For more information, please follow other related articles on the PHP Chinese website!

Vue.js improves user experience through multiple functions: 1. Responsive system realizes real-time data feedback; 2. Component development improves code reusability; 3. VueRouter provides smooth navigation; 4. Dynamic data binding and transition animation enhance interaction effect; 5. Error processing mechanism ensures user feedback; 6. Performance optimization and best practices improve application performance.

Vue.js' role in web development is to act as a progressive JavaScript framework that simplifies the development process and improves efficiency. 1) It enables developers to focus on business logic through responsive data binding and component development. 2) The working principle of Vue.js relies on responsive systems and virtual DOM to optimize performance. 3) In actual projects, it is common practice to use Vuex to manage global state and optimize data responsiveness.

Vue.js is a progressive JavaScript framework released by You Yuxi in 2014 to build a user interface. Its core advantages include: 1. Responsive data binding, automatic update view of data changes; 2. Component development, the UI can be split into independent and reusable components.

Netflix uses React as its front-end framework. 1) React's componentized development model and strong ecosystem are the main reasons why Netflix chose it. 2) Through componentization, Netflix splits complex interfaces into manageable chunks such as video players, recommendation lists and user comments. 3) React's virtual DOM and component life cycle optimizes rendering efficiency and user interaction management.

Netflix's choice in front-end technology mainly focuses on three aspects: performance optimization, scalability and user experience. 1. Performance optimization: Netflix chose React as the main framework and developed tools such as SpeedCurve and Boomerang to monitor and optimize the user experience. 2. Scalability: They adopt a micro front-end architecture, splitting applications into independent modules, improving development efficiency and system scalability. 3. User experience: Netflix uses the Material-UI component library to continuously optimize the interface through A/B testing and user feedback to ensure consistency and aesthetics.

Netflixusesacustomframeworkcalled"Gibbon"builtonReact,notReactorVuedirectly.1)TeamExperience:Choosebasedonfamiliarity.2)ProjectComplexity:Vueforsimplerprojects,Reactforcomplexones.3)CustomizationNeeds:Reactoffersmoreflexibility.4)Ecosystema

Netflix mainly considers performance, scalability, development efficiency, ecosystem, technical debt and maintenance costs in framework selection. 1. Performance and scalability: Java and SpringBoot are selected to efficiently process massive data and high concurrent requests. 2. Development efficiency and ecosystem: Use React to improve front-end development efficiency and utilize its rich ecosystem. 3. Technical debt and maintenance costs: Choose Node.js to build microservices to reduce maintenance costs and technical debt.

Netflix mainly uses React as the front-end framework, supplemented by Vue for specific functions. 1) React's componentization and virtual DOM improve the performance and development efficiency of Netflix applications. 2) Vue is used in Netflix's internal tools and small projects, and its flexibility and ease of use are key.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SublimeText3 Chinese version
Chinese version, very easy to use

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

Dreamweaver CS6
Visual web development tools

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

Zend Studio 13.0.1
Powerful PHP integrated development environment