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