vue原始碼探究(第五彈)
vue原始碼探究(第五彈)
不知不覺,到了vue原始碼探究的最後一部分,也是最為複雜的一部分,資料劫持和資料的雙向繫結。
資料劫持
資料劫持我們也可以稱為資料繫結。
- 初始化顯示:頁面(表示式/指令)能從data讀取資料顯示(編譯/解析)
- 更新顯示:更新data中的屬性資料 ===》 頁面更新
相關問題 prepare
-
dep
- 與data中的屬性一一對應
-
watcher
- 與模板中一般指令/大括號表示式一一對應
-
什麼時候一個dep中關聯多個watcher?
多個指令或表示式用到了當前同一個屬性{{name}} {{name}} -
什麼時候一個watcher中關聯多個dep?
多層表示式的watcher對應多個dep{{a.b.c}}
例子:chestnut:
<div id="test"> <p>{{name}}</p> <p v-text="name"></p> <p v-text="wife.name"></p> <button v-on:click="update">更新</button> </div> <script type="text/javascript"> new MVVM({ el: '#test', data: { name: 'sadamu',// dep0 wife: { // dep1 name: 'binbin', // dep2 age: 18 // dep3 } }, methods: { update () { this.name = 'avatar' } } // 主要梳理一下,資料改變如何 -> 頁面變化 // 1. tap button -> update Fn -> this.name = 'xxx' // 2. 資料劫持中的set方法 // 3. newVal ->是object,需要observe(類似a.b.c這種) —> 不是物件,進入dep.notify // 4. notify -> 通知all watcher -> forEach -> sub.update() // 5. watcher中的update 方法,進入 run() // 6. old 和 new value 進行比較,若不同,進入callback更新介面 // 7. callback是updateFn,同上 }) </script>
Dep
接下來講講什麼是Dep?
Dep(Depend)
-
data中的每個屬性
(所有層次)
都對應一個dep物件 -
dep建立的時機?
- 在初始化define data中,每個屬性會建立對應的dep物件
- 在data中的某個屬性值被設定為新的物件的時候
-
個數
- 與data中的屬性一一對應
-
dep物件的結構
{
id, // 每個dep都有一個唯一的id
subs //包含n個對應watcher的陣列(subscribes的簡寫) 它是一個array[]
}
-
subs屬性說明
- 當一個watcher被建立時,內部會將當前watcher物件新增到對應的dep物件的subs中
- 當此data屬性的值發生變化時,所有subs中的watcher都會收到更新的通知,從而更新對應的介面
-
subs屬性說明
Watcher
繼續講講watcher
-
個數
-
模板中每一個
非事件指令
或者表示式
都對應一個watcher物件- 事件指令,eg:v-on、v-bind...
-
模板中每一個
- 監視當前表示式資料的變化
-
建立的時機
- 在初始化編譯模板的時候
-
watch物件的組成
{
vm, // vm物件
exp, // 對應指令的表示式
cb, // callback 當表示式所對應的資料發生變化時候的回撥函式
value, //當前表示式的值
depIds // 表示式中各級屬性所對應的dep物件的集合物件,它是一個物件object
}
總結
dep與watcher的關係是: n:n(多對多)
-
一個data中的屬性對應一個dep,一個dep中可能包含多個watcher
<div>{{name}}</div> <p>{{name}}</p>
-
模板中每一個
非事件指令
或表示式
都對應一個watcher,一個watcher中可能包含多個dep<div>{{a.b.c}}</div>
資料繫結使用到的2個核心技術
- defineProperty()
- 訊息訂閱與釋出