摘要:但中的視圖渲染是實時的,視圖層依賴于數據層,數據變化了,視圖層也會跟著變化,不需要手動更新。被讀取被修改運行所有運行看看我們加多一個試試這就是中的一個依賴對應多個
開始
聲明一個對象man,可以視為vue中的data
let man = { height: 180, weight: 70, wealth: 100000000 }添加Observer
作用在于將參數對象的屬性變為響應式,只要對象的屬性被讀取或者被修改都能觀察到。然后新建一個Observer實例,將man作為參數扔進去。這里的proxyData是將man的屬性代理到以man為參數的Observer實例上去。
class Observer { constructor(obj) { this.walk(obj) } walk(obj) { Object.keys(obj).forEach(prop => { this[prop] = obj[prop] this.proxyData(obj, prop) this.defineReactive(this, prop, obj[prop]) }) } proxyData(obj, prop) { let _this = this Object.defineProperty(obj, prop, { get() { return _this[prop] }, set(newVal) { _this[prop] = newVal } }) } defineReactive(obj, prop, val) { Object.defineProperty(obj, prop, { get() { console.log(`${prop} - 被讀取!`) return val }, set(newVal) { if (newVal == val) return val = newVal console.log(`${prop} - 被修改!`) } }) } } new Observer(man)
這時打印一下man
現在man的屬性都是由Observer實例所對應的屬性的getter來返回,只有在查看時會被觸發
對man的屬性進行修改也會觸發實例對應屬性的setter
現在的Watcher有點像vue中的computed,實際上就是定義一個計算屬性,這個計算屬性依賴于前面man中的某些屬性,由他們計算而得。
class Watcher { constructor(obj, prop, computed) { this.getVal(obj, prop, computed) } getVal(obj, prop, computed) { Object.defineProperty(obj, prop, { get() { console.log(`computed屬性 - ${prop}被讀取!`) return computed() }, set() { console.error("計算屬性不可被修改!") } }) } } new Watcher(man, "strength", () => { let {height, weight} = man if (height > 160 && weight > 70) return "strong" return "weak" })
看起來沒什么問題,所依賴的屬性如果變了,計算屬性只要再被查看(get方法)一次就可以更新了。但vue中的視圖渲染是實時的,視圖層依賴于數據層,數據變化了,視圖層也會跟著變化,不需要手動更新。類比到這個例子就是計算屬性如何才能在其所依賴的屬性發生變化時被通知從而觸發應有的事件?
這時我們先給Watcher加多一個callback,用于處理當依賴的數據被修改時,我這個計算屬性該怎么響應
比如當依賴被修改時,我們就把這個計算屬性的值打印出來
class Watcher { constructor(obj, prop, computed, callback) { this.getVal(obj, prop, computed, callback) } new Watcher(man, "strength", () => { let {height, weight} = man if (height > 160 && weight > 70) return "strong" return "weak" }, () => { console.log(`i am so ${man.strength} !`) })
一切都準備好了,接下來就是該如何實現?
我們先看下Watcher中getVal這個方法
getVal(obj, prop, computed, callback) { Object.defineProperty(obj, prop, { get() { console.log(`computed屬性 - ${prop}被讀取!`) return computed() }, set() { console.error("計算屬性不可被修改!") } }) }
當我們查看計算屬性時,會調用computed這個方法,相當于查看了其所依賴的height和weight屬性,而在上面我們已經讓man的所有屬性都擁有了get方法,即他們被查看時我們是不是可以把callback塞給他們?
這時候我們引進一個橋梁,來連接Watcher和Observer。
Dep的用處在于當某一個屬性(以下稱‘自己’)被依賴了,將依賴自己的粉絲(們)--也就是Watcher(s),收集起來,假如自己發生了變化,能夠及時通知粉絲們。
class Dep { constructor() { this.deps = [] } getDeps() { if (!Dep.target || this.deps.includes(Dep.target)) return console.log("依賴添加", Dep.target) this.deps.push(Dep.target) } notify() { this.deps.forEach(dep => { dep() }) } }
這里的Dep.target就是前面所說的callback方法了。這時我們改一下Watcher中的getVal
getVal(obj, prop, computed, callback) { Object.defineProperty(obj, prop, { get() { Dep.target = callback console.log(`computed屬性 - ${prop}被讀取!`) return computed() }, set() { console.error("計算屬性不可被修改!") } }) }
在計算屬性被查看時,將callback賦值給Dep.target,接下來就會調用其所依賴屬性的getter,我們只要在getter里把callback給收集起來就行了。接下來修改依賴屬性的getter方法。
defineReactive(obj, prop, val) { let dep = new Dep() Object.defineProperty(obj, prop, { get() { console.log(`${prop} - 被讀取!`) dep.getDeps() // 依賴收集 return val }, set(newVal) { if (newVal == val) return val = newVal console.log(`${prop} - 被修改!`) } }) }
這時watcher的callback都被依賴屬性給收集起來了,當依賴屬性發生變化時只要去運行這些callback就可以了。接下來就是修改依賴屬性的setter方法。
defineReactive(obj, prop, val) { let dep = new Dep() Object.defineProperty(obj, prop, { get() { console.log(`${prop} - 被讀取!`) dep.getDeps() return val }, set(newVal) { if (newVal == val) return val = newVal console.log(`${prop} - 被修改!`) dep.notify() // 運行所有callback } }) }
運行看看
我們加多一個Watcher試試
new Watcher(man, "isGreat", () => { let {height, weight, wealth} = man if (height > 180 && weight > 70 && wealth > 100000) return "Great!" return "not good enough ..." }, () => { console.log(`they say i am ${man.isGreat}`) })
這就是vue中的一個依賴對應多個Watcher
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101580.html
摘要:總結最后我們依照下圖參考深入淺出,再來回顧下整個過程在后,會調用函數進行初始化,也就是過程,在這個過程通過轉換成了的形式,來對數據追蹤變化,當被設置的對象被讀取的時候會執行函數,而在當被賦值的時候會執行函數。 前言 Vue 最獨特的特性之一,是其非侵入性的響應式系統。數據模型僅僅是普通的 JavaScript 對象。而當你修改它們時,視圖會進行更新。這使得狀態管理非常簡單直接,不過理解...
摘要:淺析響應式原理一的特點之一是響應式,視圖隨著數據的更新而更新,在視圖中修改數據后實例中的數據也會同步更新。對于每個響應式數據,會有兩個實例,第一個是在中的閉包遍歷,用途顯而易見。接收一個回調函數,會在重新求值且值更新后執行。 淺析Vue響應式原理(一) Vue的特點之一是響應式,視圖隨著數據的更新而更新,在視圖中修改數據后Vue實例中的數據也會同步更新。內部借助依賴(下文中的Dep類)...
摘要:響應式數據響應式數據不是憑空出現的。對于對象而言,如果是之前不存在的屬性,首先可以將進行響應化處理比如調用,然后將對具體屬性定義監聽比如調用函數,最后再去做賦值,可能具體的處理過程千差萬別,但是內部實現的原理應該就是如此僅僅是猜測。 前言 首先歡迎大家關注我的Github博客,也算是對我的一點鼓勵,畢竟寫東西沒法獲得變現,能堅持下去也是靠的是自己的熱情和大家的鼓勵。 國內前端算...
摘要:所以我今后打算把每一個內容分成白話版和源碼版。有什么錯誤的地方,感謝大家能夠指出響應式系統我們都知道,只要在實例中聲明過的數據,那么這個數據就是響應式的。什么是響應式,也即是說,數據發生改變的時候,視圖會重新渲染,匹配更新為最新的值。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于 V...
閱讀 1523·2023-04-26 02:03
閱讀 4707·2021-11-22 13:53
閱讀 4579·2021-09-09 11:40
閱讀 3782·2021-09-09 09:34
閱讀 2125·2019-08-30 13:18
閱讀 3501·2019-08-30 11:25
閱讀 3295·2019-08-26 14:06
閱讀 2545·2019-08-26 13:52