Vue雙向數據綁定原理分析(轉)

add by zhj: 目前組裏使用的是前端技術是jQuery + Bootstrap,後端使用的Django,Flask等,模板是在後端渲染的。先後端沒有分離,這種作法有幾個缺點前端

1. 模板通常是由前端工程師完成的,但因爲模板的渲染是在後端,因此須要學點後端技術。對於咱們組來講,就是要學點Pythonvue

2. 因爲先後端在一塊兒,因此上線也是一塊兒的。即便只修改了前端,後端也要被迫跟着一塊兒上線,對於大點的系統來講,後端的上線耗時比較長。這有點麻煩react

3. 從技術上來說,前端技術和後端技術是獨立發展的,因此他們的交互也天然是前端後分離的。若是不用先後端分離,那前端就沒法使用更牛逼的前端技術,git

好比Vue,Angular等。github

    我以前用jQuery + Bootstrap感受還不錯,但學了Vue,感受Vue的確是比jQuery + Bootstrap更好用,Vue是使用了MVVM模式,MVVM的思想真的很牛逼,後端

把數據與顯示分開處理,經過前端框架(如Angular,Vue)實現數據與顯示的綁定,這種分開處理使前端代碼更容易開發和維護,邏輯更清晰。看了廖雪峯的前端框架

文章才知道,MVVM原來是由微軟提出來的,牛逼,贊一個。服務器

 

做者:luobo_tang
原文:https://www.jianshu.com/p/d3a15a1f94a0
來源:簡書前端工程師

關於雙向數據綁定

當咱們在前端開發中採用MV*的模式時,M - model,指的是模型,也就是數據,V - view,指的是視圖,也就是頁面展示的部分。一般,咱們須要編寫代碼,將從服務器獲取的數據進行「渲染」,展示到視圖上。每當數據有變動時,咱們會再次進行渲染,從而更新視圖,使得視圖與數據保持一致。也就是:框架

 
Paste_Image.png

而另外一方面,頁面也會經過用戶的交互,產生狀態、數據的變化,這個時候,咱們則編寫代碼,將視圖對數據的更新同步到數據,以至於同步到後臺服務器。也就是:

 
Paste_Image.png

不一樣的前端 MV* 框架對於這種 Model 和 View 間的數據同步有不一樣的處理。在 Backbone 中,Model 到 View 的數據傳遞,能夠在 View 中監聽 Model 的 change 事件,每當 Model 更新,View 中從新執行 render。而 View 到 Model 的數據傳遞,能夠監聽 View 對應的 DOM 元素的各類事件,在檢測到 View 狀態變動後,將變動的數據發送到 Model。相較於 Backbone,AngularJS 所表明的 MVVM 框架則更進一步,從框架層面支持這種數據同步機制,並且是雙向數據綁定:

 
Paste_Image.png

不過在不一樣的 MVVM 框架中,實現雙向數據綁定的技術有所不一樣。

AngularJS 採用「髒值檢測」的方式,數據發生變動後,對於全部的數據和視圖的綁定關係進行一次檢測,識別是否有數據發生了改變,有變化進行處理,可能進一步引起其餘數據的改變,因此這個過程可能會循環幾回,一直到再也不有數據變化發生後,將變動的數據發送到視圖,更新頁面展示。若是是手動對 ViewModel 的數據進行變動,爲確保變動同步到視圖,須要手動觸發一次「髒值檢測」。

VueJS 則使用 ES5 提供的 Object.defineProperty() 方法,監控對數據的操做,從而能夠自動觸發數據同步。而且,因爲是在不一樣的數據上觸發同步,能夠精確的將變動發送給綁定的視圖,而不是對全部的數據都執行一次檢測。

參考:

Vue 雙向數據綁定實現

數據與視圖的綁定與同步,最終體如今對數據的讀寫處理過程當中,也就是 Object.defineProperty() 定義的數據 set、get 函數中。Vue 中對於的函數爲 defineReactive,在精簡版實現中,我只保留了一些基本特性:

function defineReactive(obj, key, value) { var dep = new Dep() Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter() { if (Dep.target) { dep.depend() } return value }, set: function reactiveSetter(newVal) { if (value === newVal) { return } else { value = newVal dep.notify() } } }) }

在對數據進行讀取時,若是當前有 Watcher(對數據的觀察者吧,watcher 會負責將獲取的新數據發送給視圖),那將該 Watcher 綁定到當前的數據上(dep.depend(),dep 關聯當前數據和全部的 watcher 的依賴關係),是一個檢查並記錄依賴的過程。而在對數據進行賦值時,若是數據發生改變,則通知全部的 watcher(藉助 dep.notify())。這樣,即使是咱們手動改變了數據,框架也可以自動將數據同步到視圖。

 
Paste_Image.png

數據綁定關係的識別過程

Vue 和 AngularJS 中,都是經過在 HTML 中添加指令的方式,將視圖元素與數據的綁定關係進行聲明。例如:

<form id="test">
  <input type="text" v-model="name">
</form>

以上的 HTML 代碼表示該 input 元素與 name 數據進行綁定。在 JS 代碼中能夠這樣進行初始化:

var vm = new Vue({ el: '#test', data: { name: 'luobo' } })

代碼正確執行後,頁面上 input 元素對應的位置會顯示上面代碼中給出的初始值:luobo。

因爲雙向數據綁定已經創建,所以:

  • 執行 vm.name = 'mickey' 後,頁面上 input 也會更新爲顯示: mickey
  • 在頁面文本框中修改內容爲:tang,則經過vm.name 獲取的值爲:"tang"

那麼初始化的過程當中,Vue 是如何識別出這種綁定關係的呢?

經過分析源碼,在初始化過程當中(new Vue() 執行時),主要執行兩個步驟:

  • compile
  • link

compile 過程當中,對於給定的目標元素進行解析,識別出全部綁定在元素(經過 el 屬性傳入)上的指令。
link 過程當中,創建這些指令與對應數據(經過 data 屬性傳入初始值)的綁定關係,並以數據的初始值進行渲染。綁定關係創建後,就能夠雙向同步數據了。

除了基本的雙向數據綁定,Vue 還提供了更多的特性和功能,若是隻是對雙向數據綁定感興趣,能夠看下個人精簡版實現:
https://github.com/luobotang/simply-vue 基本是從 Vue 代碼中精簡、改造獲得的,主要保留了 Vue 中與雙向數據綁定有關的部分(包括 compile、link 相關代碼),指令只保留了 input[type="text"] 和普通文本兩種類型,用於演示數據綁定的效果。

相關文章
相關標籤/搜索