Vue 的響應式原理
阿新 • • 發佈:2021-10-28
1. 前言
-
當
data
中的資料發生改變,Vue內部是如何監聽message資料的改變?使用
Object.defineProperty
-----> 監聽物件屬性的改變 -
當資料發生改變,Vue是如何知道要通知哪些人?哪些頁面進行更新?
使用 釋出訂閱者模式 實現
2. 過程
2.1 首先new Vue()
new Vue({
el: "#app",
data: {
name: "fct",
age: 18
}
})
2.2 針對data
中的資料
利用Object.defineProperty
對data物件中的資料進行重構,設定get
、set
。用以監聽資料的改變。
new Observer(data); // 處理data // 觀察者 class Observer { constructor(data) { // data 即為 Vue中data物件資料 this.data = data; Object.keys(data).forEach(item => { this.defineReactive(this.data, key, data[key]) }) } defineReactive(obj, key, val) { // 一個屬性 key ,對應一個 Dep 物件 const dep = new Dep(); Object.defineProperty(obj, key, { enumerable: true, configurable: true, set(newValue) { if (newValue === value) { return; } value = newValue; // 通知訂閱者物件watcher,進行檢視更新 dep.notify(); }, get() { // 新增到訂閱者佇列 if (Dep.target) { // target 即為watcher dep.addSub(Dep.target); } return value; } }) } }
-
每個data中的屬性都對應一個Dep物件(
dependence
依賴),其中有屬性:subs
(訂閱者subscriber
),該屬性對應的值是陣列,陣列中每一項為watcher
物件(觀察者)。class Dep { constructor() { this.subs = [] // 存放watcher物件陣列 } notify() { // 通知subs物件中所有watcher,進行更新 // watcher 物件都有update方法進行檢視更新 this.subs.forEach(sub => { sub.update(); }) } addSub(sub) { // 新增 watcher物件 this.subs.push(sub); } }
2.3 針對 el
模板
解析模板中何處使用了data
中的資料,為每一處使用建立一個watcher
物件。並將物件推入到相應data
資料的Dep
物件的subs
陣列中。
new Compiler('el', this); //處理el('#app')
class Compiler { //編譯
constructor() {
// ....
new Watcher(); //編譯時找到{{}}使用了data中的屬性,新建watcher物件
}
}
class Watcher {
constructor() {
Dep.target = this; //1. 設定target,getter中if滿足條件
this.update(); //2. 進訂閱者陣列
Dep.target = null; //3. 賦空
}
update() {
// 更新檢視, this.node.nodeValue設定值
this.node.nodeValue = this.vm[this.name]; // this.vm即為Vue例項
// this.vm[this.name]取屬性值,會呼叫data物件屬性的getter,然後新增進sub陣列
}
}
3. 總結
人生人山人海人來人往,自己自尊自愛自由自在。
本文來自部落格園,作者:青檸i,轉載請註明原文連結:https://www.cnblogs.com/fuct/p/15475679.html