天天看點

前端架構師之吾見-雙向資料綁定原理及實作

作者:chandan

在《前端架構師之吾見》第三篇中介紹了 MVVM 模式,提及到 View 和 ViewModel 之間存在着互動。但好奇的讀者可能會發現與 MVC、MVP 不同的是上篇并未提及 View 和 ViewModel 之間的互動是什麼,是“發送狀态改變”、“發送使用者動作”、“更新”,還是其他?本篇正是解答這一問題的。

在 MVVM 模式,View 和 ViewModel 之間的雙向互動是通過一種叫做資料綁定(Data Binding)的技術實作的。下面将着重介紹資料綁定技術原理及實作。

前端架構師之吾見-雙向資料綁定原理及實作

MVVM 中的資料綁定

資料綁定

資料綁定是指視圖(View)的變化能實時讓視圖資料模型(ViewModel)發生變化,反之資料的變化也能實時更新到視圖(View)。其核心的原理是采用資料劫持結合觀察者(釋出-訂閱)模式,通過代理模式(Object.defineProperty 或 Proxy)對屬性的 get 和 set 進行攔截或重置。在資料發生變化的時候發消息給訂閱者,觸發相應的監聽回調函數。

前端架構師之吾見-雙向資料綁定原理及實作

MVVM 中雙向資料綁定流程

下面将一一講解雙向資料綁定中涉及到核心技術點。其中觀察者模式及代理模式屬于經典的設計模式。

觀察者模式

觀察者模式又稱為釋出-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式或源-監聽器(Source/Listener)模式,是定義對象間的一種一對多依賴關系,使得每當一個對象狀态發生改變時,其相應依賴對象都能得到通知及更新。

前端架構師之吾見-雙向資料綁定原理及實作

觀察者設計模式

代理模式

代理模式是給某一個對象提供一個代理,并由代理對象控制原對象的引用,是一種對象結構性設計模式。

前端架構師之吾見-雙向資料綁定原理及實作

代理設計模式

資料劫持

是一種通過 hack 的方式,在通路或修改對象屬性時,攔截預設行為,進行額外的操作并傳回新的結果。在 Javascript 中常見的資料劫持可通過 Object.defineProperty() 或 Proxy 來實作。鑒于 Object.defineProperty() 的性能開銷及對數組 push、unshift、splice 等操作無法監聽等問題及 ES6+ 得到大量應用,更推薦采用 Proxy 來實作資料劫持。

代碼實作

簡易實作

// index.html
<head>
  <script type='application/javascript' src='./data-binding.js' />
</head>
...
<input data-bind='name' type='text' />
  {{name}}
...

// data-binding.js
class MVVM {
	constructor() {
    this.element = document.getAttribute('data-bind');
  	this.observe();
    this.render();
  }
  
  observe(){
  	this.data = new Proxy(this.data, {
    	get: (target, key) => target[key],
      set: (target, key, newValue) => {
      	target[key] = newValue;
        this.render();
      }
    });
  }
  
  render() {
  	this.element.innerHTML = `${this.data}`;
  }
}
           

Vuejs 中的雙向綁定

Vuejs 中的雙向資料綁定是通過 v-model 指令來實作的,具體代碼實作可參見 vuejs 項目源碼。

https://github.com/vuejs/core/blob/main/packages/compiler-core/src/parse.ts

繼續閱讀