1. 程式人生 > 其它 >Vue 的響應式原理

Vue 的響應式原理

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物件中的資料進行重構,設定getset。用以監聽資料的改變。

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