簡單實現vue中的依賴收集與響應

2021-09-12 15:47:30 字數 3277 閱讀 3984

宣告乙個物件man,可以視為vue中的data

let man =
作用在於將引數物件的屬性變為響應式,只要物件的屬性被讀取或者被修改都能觀察到。然後新建乙個observer例項,將man作為引數扔進去。這裡的proxydata是將man的屬性**到以man為引數的observer例項上去。

class observer 

walk(obj) )

} proxydata(obj, prop) ,

set(newval)

})} definereactive(obj, prop, val) - 被讀取!`)

return val

},set(newval) - 被修改!`)}})

}}new observer(man)

這時列印一下man

現在man的屬性都是由observer例項所對應的屬性的getter來返回,只有在檢視時會被觸發

對man的屬性進行修改也會觸發例項對應屬性的setter

現在的watcher有點像vue中的computed,實際上就是定義乙個計算屬性,這個計算屬性依賴於前面man中的某些屬性,由他們計算而得。

class watcher 

getval(obj, prop, computed) 被讀取!`)

看起來沒什麼問題,所依賴的屬性如果變了,計算屬性只要再被檢視(get方法)一次就可以更新了。但vue中的檢視渲染是實時的,檢視層依賴於資料層,資料變化了,檢視層也會跟著變化,不需要手動更新。模擬到這個例子就是計算屬性如何才能在其所依賴的屬性發生變化時被通知從而觸發應有的事件?

這時我們先給watcher加多乙個callback,用於處理當依賴的資料被修改時,我這個計算屬性該怎麼響應

比如當依賴被修改時,我們就把這個計算屬性的值列印出來

class watcher 

new watcher(man, 'strength', () => = man

if (height > 160 && weight > 70) return 'strong'

return 'weak'

}, () => !`)

})

一切都準備好了,接下來就是該如何實現?

我們先看下watcher中getval這個方法

getval(obj, prop, computed, callback) 被讀取!`)

return computed()

},set() })}

當我們檢視計算屬性時,會呼叫computed這個方法,相當於檢視了其所依賴的height和weight屬性,而在上面我們已經讓man的所有屬性都擁有了get方法,即他們被檢視時我們是不是可以把callback塞給他們?

這時候我們引進乙個橋梁,來連線watcher和observer。

dep的用處在於當某乙個屬性(以下稱『自己』)被依賴了,將依賴自己的粉絲(們)--也就是watcher(s),收集起來,假如自己發生了變化,能夠及時通知粉絲們。

class dep 

getdeps()

notify() )

}}

這裡的dep.target就是前面所說的callback方法了。這時我們改一下watcher中的getval

getval(obj, prop, computed, callback) 被讀取!`)

return computed()

},set() })}

在計算屬性被檢視時,將callback賦值給dep.target,接下來就會呼叫其所依賴屬性的getter,我們只要在getter裡把callback給收集起來就行了。接下來修改依賴屬性的getter方法。

definereactive(obj, prop, val)  - 被讀取!`)

dep.getdeps() // 依賴收集

return val

},set(newval) - 被修改!`) }})

}

這時watcher的callback都被依賴屬性給收集起來了,當依賴屬性發生變化時只要去執行這些callback就可以了。接下來就是修改依賴屬性的setter方法。

definereactive(obj, prop, val)  - 被讀取!`)

dep.getdeps()

return val

},set(newval) - 被修改!`)

dep.notify() // 執行所有callback}})

}

執行看看

我們加多乙個watcher試試

這就是vue中的乙個依賴對應多個watcher

簡單實現vue中的依賴收集與響應

宣告乙個物件man,可以視為vue中的data let man 作用在於將引數物件的屬性變為響應式,只要物件的屬性被讀取或者被修改都能觀察到。然後新建乙個observer例項,將man作為引數扔進去。這裡的proxydata是將man的屬性 到以man為引數的observer例項上去。class o...

vue原始碼系列06 實現陣列的依賴收集

在初始化資料的時候,建立乙個陣列專用的dep 給每個物件新增乙個ob屬性,主要是用於儲存當前例項物件 this 在 array.js 中在資料改變時,觸發陣列專用dep的notify 派發更新 修改 definereactive 方法 export function definereactive d...

vue的雙向繫結和依賴收集

在掘金上買了乙個關於解讀vue原始碼的小冊,因為是付費的,所以還比較放心 在小冊裡看到了關於vue雙向繫結和依賴收集的部分,總感覺有些怪怪的,然後就自己跟著敲了一遍。敲完後,發現完全無法執行,坑啊,寫書人完全沒有測試過。然後自己完善 越寫越發現坑,問題有些大。最後自己重新實現了一遍,較多。用到觀察訂...