Vue provide/inject 部分源码分析 实现响应式数据更新

 

 

provide/inject 数据响应式更新的坑及源码解析css

 

下面是我本身曾经遇到 一个问题,直接以本身QA的形式来写吧segmentfault

自问自答了,须要的同窗也能够直接访问segmentfault地址数组

官网给出实例,说自己是不支持数据响应式的, 可是能够传入响应式数据,那么provide,inject就能够实现响应式。
我这里理解应该没错哈,有不对的地方请指出。缓存

 

我本身写的demo,作了以下更改ide

parent 页面:函数

export default { provide(){ return {foo:this.fonnB} }, data(){ return {fonnB:'old word'} } created() { setTimeout(()=>{ this.fonnB="new words"; // 这种跟新,仅仅foonB变化了,foo没有变化 this._provided.foo="new words"; //这种更新 foo变化了,但子组件得到的foo 依旧是old words console.log( this._provided) },1000) }, }

child页面:ui

 
export default { inject:['foo'], data(){ return {chilrfoo:this.foo} } } 经过上面2个方法,通过验证,子组件页面都没办法实现响应更新this.foo的值。 求解释,谢谢


以上是我本身的问题, 下面是我基本理解后,在本身回答的问题

现作了以下修改,能够达到父亲组件改变,下面的孙子组件都能更新数据.这样就是传入了一个响应式数据,若是须要双向数据的话,须要在child页面的computed 中手动写set 函数,computed 自己就只至关于一个get函数。this

值得注意是:child页面data 数据中childfooOld并不会响应。若是这里childfooOld=this.foo ,obj的形式也是能够响应的,那么a也是响应式数据。
若是是单数据格式不能响应,childfooOld下没有set/get 只是在data下的set/get 是控制data下属性变化时触发的,而不是this.foo.a 触发的;spa

parent页面:
export default {code

provide(){
     return {foo:this.fonnB} }, data(){ return { fonnB:{a:'old word'} } } created() { setTimeout(()=>{ this.fonnB.a="new words"; //这种更新 foo变化了,但子组件得到的foo 依旧是old words },1000) }, }

child页面:

export default { inject:['foo'], data(){ return { childfooOld:this.foo.a } }, computed:{ chilrfoo(){ return this.foo.a } } } 

关于prodive 和inject 源码部分以下
export function initInjections (vm: Component) {
const result = resolveInject(vm.$options.inject, vm)
if (result) {

observerState.shouldConvert = false Object.keys(result).forEach(key => { defineReactive(vm, key, result[key]) }) observerState.shouldConvert = true

}
}
能够看出 prodive 也运用了defineReactive 函数,增长了自身的set,get函数,也是响应式数据,以下图

    

 

 

以下 是inject 源码,我没看出来那里明确增长了set/get,可是打印出来结果inject 也是有set/get的

export function resolveInject (inject: any, vm: Component): ?Object {
if (inject) {

// inject 是 :any 类型由于流没有智能到可以指出缓存 const result = Object.create(null) // 获取 inject 选项的 key 数组 const keys = hasSymbol ? Reflect.ownKeys(inject).filter(key => { /* istanbul ignore next */ return Object.getOwnPropertyDescriptor(inject, key).enumerable }) : Object.keys(inject) for (let i = 0; i < keys.length; i++) { const key = keys[i] const provideKey = inject[key].from let source = vm while (source) { if (source._provided && provideKey in source._provided) { 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

}
}

 

 

经过computed 就实现了上下传值固然能够直接 经过绑定data属性,可是不能时单数据绑定

相关文章
相关标签/搜索