摘要:與狀態同步非常困難通過添加觀察者監測變化,如和。應用中狀態的屬性會被監測,當它們發生變化時,只有依賴了發生變化屬性的元素會被重新渲染。
現代 js 框架存在的根本原因
然而通常人們(自以為)使用框架是因為:
它們支持組件化;
它們有強大的社區支持;
它們有很多(基于框架的)第三方庫來解決問題;
它們有很多(很好的)第三方組件;
它們有瀏覽器擴展工具來幫助調試;
它們適合做單頁應用。
Keeping the UI in sync with the state is hard (UI與狀態同步非常困難)
通過(添加)觀察者監測變化,如 Angular 和 Vue.js。應用中狀態的屬性會被監測,當它們發生變化時,只有依賴了(發生變化)屬性的 DOM 元素會被重新渲染。
1.屬性攔截器-初步數據劫持
Object.defineProperty()
let a = {} Object.defineProperty(a, "b", { enumerable: true, configurable: true, set (newValue){ console.log("set") value = newValue }, get (){ console.log("get") return value } }) value = a.b a.b = 1 console.log(a.b)
讀a.b或者設置a.b時候觸發get和set函數
configurable如果為false,那么不可以修改, 不可以刪除.
writable給的說明是如果設置為false,不可以采用 數據運算符,進行賦值
2.想實現一個這樣的功能
當我們試圖修改 a 的值時:ins.a = 2,在控制臺將會打印 "修改了 a’,
乍一看比較簡單
考慮到復雜情況,
比如如何避免收集重復的依賴,如何深度觀測,如何處理數組以及其他邊界條件等等
const ins = new Vue({ data: { a: 1 } }) ins.$watch("a", () => { console.log("修改了 a") })
3.收集依賴, 起碼需要一個”筐“
// dep 數組就是我們所謂的“筐” const dep = [] Object.defineProperty(data, "a", { set () { // 當屬性被設置的時候,將“筐”里的依賴都執行一次 dep.forEach(fn => fn()) }, get () { // 當屬性被獲取的時候,把依賴放到“筐”里 dep.push(fn) } }) $watch("a", () => { console.log("設置了 a") })
4.$watch 函數是知道當前正在觀測的是哪一個字段的
const data = { a: 1 } const dep = [] Object.defineProperty(data, "a", { set () { dep.forEach(fn => fn()) }, get () { // 此時 Target 變量中保存的就是依賴函數 dep.push(Target) } }) // Target 是全局變量 let Target = null function $watch (exp, fn) { // 將 Target 的值設置為 fn Target = fn // 讀取字段值,觸發 get 函數 data[exp] }
明白數據響應系統的整體思路,為接下來真正進入 Vue 源碼做必要的鋪墊
4.observer
observe工廠函數
const data = { a: 1 } const data = { a: 1, // __ob__ 是不可枚舉的屬性 __ob__: { value: data, // value 屬性指向 data 數據對象本身,這是一個循環引用 dep: dep實例對象, // new Dep() vmCount: 0 } }
new Observer(data)
Observer構造函數-調用this.walk(value)-defineReactive(get和set)
get 調用 dep.depend() 在 get 函數中如何收集依賴
set 調用 dep.notify() 通知更新
5.dep
static target; // watcher id; //記錄id不能重復收集 subs; //數組,sub收集所以的watcher
dep.notify()實際上是 watcher里的update() 渲染更新
dep.depend()實際上是 watcher里的update() 渲染更新 把watcher實例對象推入subs
6.watcher
vm, vue實例對象
expOrFn, 表達式
cb, 回調函數
當然還在vm上定義了很多其他的computer,watch之類的
收集依賴,要想收集,必須 new watcher()
get () { pushTarget(this) } addDep (){ dep.addSub(this) // 把watcher自己加入dep.subs數組 } update(){ queueWatcher() //排隊渲染 }
6.總結
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97375.html
摘要:執行的時候,會綁定上下文對象為組件實例于是中的就能取到組件實例本身,的代碼塊頂層作用域就綁定為了組件實例于是內部變量的訪問,就會首先訪問到組件實例上。其中的獲取,就會先從組件實例上獲取,相當于。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得...
摘要:接下來要看看這個訂閱者的具體實現了實現訂閱者作為和之間通信的橋梁,主要做的事情是在自身實例化時往屬性訂閱器里面添加自己自身必須有一個方法待屬性變動通知時,能調用自身的方法,并觸發中綁定的回調,則功成身退。 本文能幫你做什么?1、了解vue的雙向數據綁定原理以及核心代碼模塊2、緩解好奇心的同時了解如何實現雙向綁定為了便于說明原理與實現,本文相關代碼主要摘自vue源碼, 并進行了簡化改造,...
摘要:儲存訂閱器因為屬性被監聽,這一步會執行監聽器里的方法這一步我們把也給弄了出來,到這一步我們已經實現了一個簡單的雙向綁定了,我們可以嘗試把兩者結合起來看下效果。總結本文主要是對雙向綁定原理的學習與實現。 當今前端天下以 Angular、React、vue 三足鼎立的局面,你不選擇一個陣營基本上無法立足于前端,甚至是兩個或者三個陣營都要選擇,大勢所趨。 所以我們要時刻保持好奇心,擁抱變化,...
摘要:所以無需太過介懷是實現的單向或雙向綁定。監聽數據綁定更新函數的處理是在這個方法中,通過添加回調來接收數據變化的通知至此,一個簡單的就完成了,完整代碼。 本文能幫你做什么?1、了解vue的雙向數據綁定原理以及核心代碼模塊2、緩解好奇心的同時了解如何實現雙向綁定為了便于說明原理與實現,本文相關代碼主要摘自vue源碼, 并進行了簡化改造,相對較簡陋,并未考慮到數組的處理、數據的循環依賴等,也...
閱讀 3480·2021-10-13 09:39
閱讀 1462·2021-10-08 10:05
閱讀 2265·2021-09-26 09:56
閱讀 2283·2021-09-03 10:28
閱讀 2681·2019-08-29 18:37
閱讀 2039·2019-08-29 17:07
閱讀 606·2019-08-29 16:23
閱讀 2198·2019-08-29 11:24