Vue|Vue 2源码阅读 Provide Inject 依赖注入详解
目录
- Provide/Inject 初始化
- 1. initInjections 依赖初始化
- 2. initProvide 注入数据初始化
- 总结
Provide/Inject 初始化
1. initInjections 依赖初始化
该步骤其实发生在 initState 之前,但是由于 provide/inject 一般是配合使用,所以这里调整了一下顺序。
该函数的定义与过程都比较简单:
export function initInjections(vm: Component) {const result = resolveInject(vm.$options.inject, vm)if (result) {toggleObserving(false)Object.keys(result).forEach(key => {if (__DEV__) {defineReactive(vm, key, result[key], () => warn(''))} else {defineReactive(vm, key, result[key])}})toggleObserving(true)}}export function resolveInject(inject: any, vm: Component): Record | undefined | null {if (inject) {const result = Object.create(null)const keys = hasSymbol ? Reflect.ownKeys(inject) : Object.keys(inject)for (let i = 0; i < keys.length; i++) {const key = keys[i]if (key === '__ob__') continueconst provideKey = inject[key].fromif (provideKey in vm._provided) {result[key] = vm._provided[provideKey]} else if ('default' in inject[key]) {const provideDefault = inject[key].defaultresult[key] = isFunction(provideDefault) ? provideDefault.call(vm) : provideDefault} else if (__DEV__) {warn('')}}return result}}
- 在 initInjections 函数中,只是遍历了 options.inject 配置的依赖数据,并 关闭 了依赖数据的 响应式依赖收集,最后通过 defineReactive 将对应的数据挂载到实例 vm 上,以便后面能直接访问。
- 而 resolveInject 函数就是用来对组件的 inject 依赖数据进行处理,并返回一个没有多余原型链的对象。
但是,在 mergeOptions 之后,会将 options.inject 转为标准对象格式。
并且这里并没有对注入数据 provide[key] 进行处理,而是直接赋值;所以才有:如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。
resolveInject() 函数就是解析标准格式 inject 配置,并将上层组件的 provide 的值或者 default 默认值绑定到函数返回对象中;如果这两个都没有,则会提示错误信息 “injection xx not found”
2. initProvide 注入数据初始化
初始化注入数据的过程也很简单,整个过程其实与 initInjection 类似。其函数定义如下:
export function initProvide(vm: Component) {const provideOption = vm.$options.provideif (provideOption) {const provided = isFunction(provideOption) ? provideOption.call(vm) : provideOptionif (!isObject(provided)) {return}const source = resolveProvided(vm)const keys = hasSymbol ? Reflect.ownKeys(provided) : Object.keys(provided)for (let i = 0; i < keys.length; i++) {const key = keys[i]Object.defineProperty(source,key,Object.getOwnPropertyDescriptor(provided, key)!)}}}export function resolveProvided(vm: Component): Record {const existing = vm._providedconst parentProvides = vm.$parent && vm.$parent._providedif (parentProvides === existing) {return (vm._provided = Object.create(parentProvides))} else {return existing}}
官方文档中对 provide 配置项的说明是,可以是一个对象或者一个返回对象的函数。
- 所以这里首先判断了 options.provide 的类型并获取到了结果,如果结果 不是对象则会直接退出。
- 然后,则是初始化 provide 的数据。
因为每一个实例都会进行与父组件实例的注入数据比较,所以才能多层级传递
- 最后,则是遍历 provided 对象,通过 Object.defineProperty 来处理数据获取。
总结 整个 provide/inject 的初始化过程都很清晰,只是通过少数校验和处理,将 provide 数据一层一层传递下去,直到 inject 依赖时读该改数据的值;
并且因为在初始化时会关闭响应式处理部分,所以 provide/inject 的 直接绑定数据 才不支持响应式;但
又因为 没有对数据的进行深层次处理,所以,原有的响应式数据才会继续触发整个响应式系统的改变。
以上就是Vue 2源码阅读 Provide Inject 依赖注入详解的详细内容,更多关于Vue Provide Inject 依赖注入的资料请关注脚本之家其它相关文章!
推荐阅读
- java|Ssm美众针纺有限公司人事管理毕业设计源码051708
- java|SSM在线学习网站的设计与实现毕业设计源码011451
- VUE的JS指令
- Vue2.x与Vue3.x中路由钩子的区别详解
- spring-调试源码
- vue|Vue实战项目开发 - 项目的联调,测试与发布上线
- 【javaWeb微服务架构项目——乐优商城day02】——Vue.js(认识Vue,Node和NPM,Vue实例,指令,组件化,路由vue-router)
- 20160524——21-22期3721阅读团打卡统计情况分析报告
- 以太坊|以太坊 layer2: optimism 源码学习(二) 提现原理
- python|python写一个简单的爬虫程序(爬取快手)(附源码)