前端开发那些事儿

vue provide和inject原理(源码)

2021-07-26  本文已影响0人  vivianXIa

使用

provide和inject主要用于开发高阶插件和组件时使用。并不推荐应用于程序代码中
父组件提供foo 子组件注入

var Provider = {
  provide:{
    foo:'bar'
  },
  //....
}
//子
var Child = {
  inject:['foo'],
  created(){
    console.log(this.foo);
  }
}

缺点

数据来源不明确
重名问题

源码:

1入口位置:src/core/instance/init.js 50行左右

initInjections(vm)//子组件将数据注入到自己身上
initProvide(vm);//父组件在初始化的时候提供好数据

2:provide源码

export function initProvide(vm:component){
  const provide = vm.$options.provide
  if(provide){
     vm._provide = typeof provide === 'function' ?provide.call(vm):provide
   }
}

export default initInjection(vm:Component){
  //拿到inject属性 进行解析
  const result = resolveInject(vm.$options.inject,vm)
}

3.inject

export function resolveInject (inject: any, vm: Component): ?Object {
  if (inject) {
    // inject is :any because flow is not smart enough to figure out cached
    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]
      // #6574 in case the inject object is observed...
      if (key === '__ob__') continue
      const provideKey = inject[key].from
      let source = vm
      while (source) {
        if (source._provided && hasOwn(source._provided, provideKey)) {
          result[key] = source._provided[provideKey]
          break
        }
        source = source.$parent
      }
      if (!source) {
        if ('default' in inject[key]) {
          const provideDefault = inject[key].default
          result[key] = typeof provideDefault === 'function'
            ? provideDefault.call(vm)
            : provideDefault
        } else if (process.env.NODE_ENV !== 'production') {
          warn(`Injection "${key}" not found`, vm)
        }
      }
    }
    return result
  }
}

总结
在全局vm上添加一个属性provide存我们定义的变量,inject一层层向上查找目标属性,找到为止!

上一篇下一篇

猜你喜欢

热点阅读