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屬性,可是不能時單數據綁定