摘要:響應式原理看過官方文檔的同學,對這張圖應該已然相當熟悉了。先擼為敬這里我們用不到行的代碼,實現了一個簡易的響應式。當然,這里如果不考慮期間的過程,我相信,行代碼之內可以搞定。
Vue響應式原理
看過vue官方文檔的同學,對這張圖應該已然相當熟悉了。
vue的響應式是如何實現的?
聽過太多回答,通過Object.defineProperty,可是再詳細的問時,對方渾然不知。
先擼為敬const Observer = function(data) { for (let key in data) { defineReactive(data, key); } } const defineReactive = function(obj, key) { const dep = new Dep(); let val = obj[key]; Object.defineProperty(obj, key, { enumerable: true, configurable: true, get() { console.log("in get"); dep.depend(); return val; }, set(newVal) { if (newVal === val) { return; } val = newVal; dep.notify(); } }); } const observe = function(data) { return new Observer(data); } const Vue = function(options) { const self = this; if (options && typeof options.data === "function") { this._data = options.data.apply(this); } this.mount = function() { new Watcher(self, self.render); } this.render = function() { with(self) { _data.text; } } observe(this._data); } const Watcher = function(vm, fn) { const self = this; this.vm = vm; Dep.target = this; this.addDep = function(dep) { dep.addSub(self); } this.update = function() { console.log("in watcher update"); fn(); } this.value = fn(); Dep.target = null; } const Dep = function() { const self = this; this.target = null; this.subs = []; this.depend = function() { if (Dep.target) { Dep.target.addDep(self); } } this.addSub = function(watcher) { self.subs.push(watcher); } this.notify = function() { for (let i = 0; i < self.subs.length; i += 1) { self.subs[i].update(); } } } const vue = new Vue({ data() { return { text: "hello world" }; } }) vue.mount(); // in get vue._data.text = "123"; // in watcher update /n in get
這里我們用不到100行的代碼,實現了一個簡易的vue響應式。當然,這里如果不考慮期間的過程,我相信,40行代碼之內可以搞定。但是我這里不想省略,為什么呢?我怕你把其中的過程自動忽略掉,怕別人問你相關東西的時候,明明自己看過了,卻被懟的啞口無言。總之,我是為了你好,多喝熱水。
Dep的作用是什么?依賴收集器,這不是官方的名字蛤,我自己起的,為了好記。
用兩個例子來看看依賴收集器的作用吧。
例子1,毫無意義的渲染是不是沒必要?
const vm = new Vue({ data() { return { text: "hello world", text2: "hey", } } })
當vm.text2的值發生變化時,會再次調用render,而template中卻沒有使用text2,所以這里處理render是不是毫無意義?
針對這個例子還記得我們上面模擬實現的沒,在Vue的render函數中,我們調用了本次渲染相關的值,所以,與渲染無關的值,并不會觸發get,也就不會在依賴收集器中添加到監聽(addSub方法不會觸發),即使調用set賦值,notify中的subs也是空的。OK,繼續回歸demo,來一小波測試去印證下我說的吧。
const vue = new Vue({ data() { return { text: "hello world", text2: "hey" }; } }) vue.mount(); // in get vue._data.text = "456"; // nothing vue._data.text2 = "123"; // in watcher update /n in get
例子2,多個Vue實例引用同一個data時,通知誰?是不是應該倆都通知?
let commonData = { text: "hello world" }; const vm1 = new Vue({ data() { return commonData; } }) const vm2 = new Vue({ data() { return commonData; } }) vm1.mount(); // in get vm2.mount(); // in get commonData.text = "hey" // 輸出了兩次 in watcher update /n in get
老規矩,自己代入進去試試。
希望通過這兩個例子,你已經大概清楚了Dep的作用,有沒有原來就那么回事的感覺?有就對了??偨Y一下吧(以下依賴收集器實為Dep):
vue將data初始化為一個Observer并對對象中的每個值,重寫了其中的get、set,data中的每個key,都有一個獨立的依賴收集器。
在get中,向依賴收集器添加了監聽
在mount時,實例了一個Wathcer,將收集器的目標指向了當前Watcher
在data值發生變更時,觸發set,觸發了依賴收集器中的所有監聽的更新,來觸發Watcher.update
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94576.html
摘要:緊接著發現,于是又停了,瀏覽器下載并執行完,繼續。,發現,遂將中文字展示了出來。的執行時間是在所有元素解析完成之后,事件觸發之前。的執行時間是在當前腳本下載完成后,所以多個是執行順序是不固定的。至此,完美的結構出爐了。 現代瀏覽器性能優化-JS篇 眾所周知,JS的加載和執行會阻塞瀏覽器渲染,所以目前業界普遍推薦把script放到之前,以解決js執行時找不到dom等問題。但隨著現代瀏覽器...
摘要:緊接著發現,于是又停了,瀏覽器下載并執行完,繼續。,發現,遂將中文字展示了出來。的執行時間是在所有元素解析完成之后,事件觸發之前。的執行時間是在當前腳本下載完成后,所以多個是執行順序是不固定的。至此,完美的結構出爐了。 現代瀏覽器性能優化-JS篇 眾所周知,JS的加載和執行會阻塞瀏覽器渲染,所以目前業界普遍推薦把script放到之前,以解決js執行時找不到dom等問題。但隨著現代瀏覽器...
摘要:當觸發異常的字節碼的索引值在某個異常表條目的監控范圍內,虛擬機會判斷所拋出的異常和該條目想要捕獲的異常是否匹配。 作者:李瑞杰目前就職于阿里巴巴,狂熱JVM愛好者讓我們準備一個函數:showImg(https://user-gold-cdn.xitu.io/2019/5/19/16acbce35adfefb7);然后,反編譯他的字節碼:showImg(https://user-gold-cd...
摘要:當觸發異常的字節碼的索引值在某個異常表條目的監控范圍內,虛擬機會判斷所拋出的異常和該條目想要捕獲的異常是否匹配。 作者:李瑞杰目前就職于阿里巴巴,狂熱JVM愛好者讓我們準備一個函數:showImg(https://user-gold-cdn.xitu.io/2019/5/19/16acbce35adfefb7);然后,反編譯他的字節碼:showImg(https://user-gold-cd...
摘要:當觸發異常的字節碼的索引值在某個異常表條目的監控范圍內,虛擬機會判斷所拋出的異常和該條目想要捕獲的異常是否匹配。 作者:李瑞杰目前就職于阿里巴巴,狂熱JVM愛好者讓我們準備一個函數:showImg(https://user-gold-cdn.xitu.io/2019/5/19/16acbce35adfefb7);然后,反編譯他的字節碼:showImg(https://user-gold-cd...
閱讀 2843·2023-04-26 01:02
閱讀 1863·2021-11-17 09:38
閱讀 791·2021-09-22 15:54
閱讀 2899·2021-09-22 15:29
閱讀 888·2021-09-22 10:02
閱讀 3432·2019-08-30 15:54
閱讀 2007·2019-08-30 15:44
閱讀 1586·2019-08-26 13:46