vue的provide和inject使用方法及原理

provide / inject

应用场景

  • 父子组件通讯:替代this.$parent
  • 祖孙组件通讯: 祖先组件不需要知道哪些后代组件在使用他提供的数据;后代组件也不需要知道注入的数据来自哪里

使用方法

// 父级组件提供 'foo'
var Provider = {
  provide: {
    foo: 'bar'
  },
  // ...
}

// 子组件注入 'foo'
var Child = {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}

指定默认值

const Child = {
  inject: {
    foo: { default: 'foo' }
  }
}

指定来源

const Child = {
  inject: {
    foo: {
      from: 'bar',
      default: 'foo'
    }
  }
}

非原始值(对象类型,数组类型…) ==> 需要指定工厂方法

const Child = {
  inject: {
    foo: {
      from: 'bar',
      default: () => [1, 2, 3]
    },
   boo: {
      from: 'user',
      default: () => {name: 'micke'}
    },
  }
}

原理

provide api原理

/**
 * 当前组件实例的provide首先会指向父组件的provides
 */
const instance = {
    provide: parent ? parent.provides : Object.create(appContent.provides)
    // 其他属性
    // ...
}
/**
 * provide api
 * @param {String} key 
 * @param {Any} value 设定值
 */
function provide(key, value) {
    let provides = currentInstance.provides // 当前组件的provides
    const parentProvides = currentInstance.parent && currentInstance.parent.provides // 父组件的provides
    // 第一次调用provide api,会进入这个if,provide 和 inject 绑定并不是可响应的。这是刻意为之的
    if (parentProvides === provides) {
        provides = currentInstance.provides = Object.create(parentProvides) // 新建一个空对象,并把父组件provides挂载到原型上(__proto__)
    }
    provides[key] = value // 设定值
}
  • 组件的provide 默认等于父组件provide。
  • 当组件配置了provide时,它就会自动创建一个新的空对象保存配置的provide,同时这个新对象的原型指向父组件的provide。
  • 通过这种原型链机制,在孙组件就很容易访问到祖辈组件的provide
app(provides) 根组件(provides) 子组件(provides) 创建 创建 __proto__ __proto__ app(provides) 根组件(provides) 子组件(provides)

inject api 原理

/**
 * inject api
 * @param {String} key 
 * @param {Any} defaultValue 默认值
 */
function inject(key, defaultValue) {
    const instance = currentInstance || currentRendingInstance // 当前实例
    if (instance) {
        const provides = instance.provides
        if (key in provides) {
            return provides[key] // 如果key存在,就返回
        }
        else if (arguments.length > 1) {
            return defaultValue // key不存在,且设置了默认值,就返回默认值
        }
        else if (process.env.NODE_ENV !== 'production') {
            warn(`injection "${String(key)}" not found.`) // 报错提示
        }
    }

}
  • inject会尝试寻找目标key,包括provides的原型链
  • 没有找到key的还就返回默认值
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值