首頁  >  文章  >  web前端  >  深入理解vue.js雙向綁定的實作原理

深入理解vue.js雙向綁定的實作原理

高洛峰
高洛峰原創
2017-03-30 16:45:001681瀏覽

前言

大家都知道Vue.js最核心的功能有兩個,一是響應式的資料綁定係統,二是​​元件系統。本文僅探究幾乎所有Vue的開篇介紹都會提到的hello world雙向綁定是如何實現的。先講涉及的知識點,再參考原始碼,用盡可能少的程式碼實作那個hello world開篇範例。

一、存取器屬性

存取器屬性是物件中的一種特殊屬性,它不能直接在物件中設置,而必須透過defineProperty()方法單獨定義。

var obj = { };
 
// 为obj定义一个名为hello的访问器属性
 
Object.defineProperty(obj, "hello", {
 
get: function () {return sth},
 
set: function (val) {/* do sth */}
 
})

obj.hello // 可以像普通屬性一樣讀取訪問器屬性

訪問器屬性的"值"比較特殊,讀取或設定訪問器屬性的值,實際上是調用其內部特性:get和set函數。

obj.hello // 讀取屬性,就是呼叫get函數並回傳get函數的回傳值

obj.hello = "abc" // 為屬性賦值,就是呼叫set函數,賦值其實是傳參

深入理解vue.js雙向綁定的實作原理

get和set方法內部的this都指向obj,這表示get和set函數可以操作物件內部的值。另外,訪問器屬性的會"覆蓋"同名的普通屬性,因為訪問器屬性會被優先訪問,與其同名的普通屬性則會被忽略(也就是所謂的被"劫持"了)。

二、極簡雙向綁定的實作

深入理解vue.js雙向綁定的實作原理

此例實現的效果是:隨文字方塊輸入文字的變化,span中會同步顯示相同的文字內容;在js或控制台顯式的修改obj.name的值,視圖會相應更新。這樣就實現了model =>view以及view => model的雙向綁定,並且是響應式的。

深入理解vue.js雙向綁定的實作原理

以上就是Vue實現雙向綁定的基本原理。

三、分解任務

上述範例只是為了說明原理。

我們最終要實現的是:

深入理解vue.js雙向綁定的實作原理

深入理解vue.js雙向綁定的實作原理

首先將該任務分成幾個子任務:

   1、輸入框以及文字節點綁定與data中的資料輸入量時,data中的資料同步變化。即view => model的變化。

   3、data中的資料變化時,文字節點的內容同步變化。即model => view的變化。

要實現任務一,需要對DOM進行編譯,這裡有一個知識點:DocumentFragment。

四、DocumentFragment

DocumentFragment(文檔片段)可以看作節點容器,它可以包含多個子節點,當我們將它插入到DOM中時,只有它的子節點會插入目標節點,所以把它看作一組節點的容器。使用DocumentFragment處理節點,速度和效能遠優於直接操作DOM。 Vue進行編譯時,就是將掛載目標的所有子節點劫持(真的是劫持)到DocumentFragment中,經過一番處理後,再將DocumentFragment整體返回插入掛載目標。

深入理解vue.js雙向綁定的實作原理

深入理解vue.js雙向綁定的實作原理五、資料初始化綁定

深入理解vue.js雙向綁定的實作原理

深入理解vue.js雙向綁定的實作原理

以上程式碼實現了任務一,我們可以看到,hello world已經呈現在輸入框和文字節點中。

深入理解vue.js雙向綁定的實作原理

六、響應式的資料綁定

再來看任務二的實現思路:當我們在輸入框輸入資料的時候,先觸發input事件(或keyup、change事件),在對應的事件處理程式中,我們取得輸入框的value並賦值給vm實例的text屬性。我們會利用defineProperty將data中的text劫持為vm的存取器屬性,因此給vm.text賦值,就會觸發set方法。

在set方法中主要做兩件事,第一是更新屬性的值,第二留到任務三再說。

深入理解vue.js雙向綁定的實作原理

深入理解vue.js雙向綁定的實作原理

任務二也就完成了,text屬性值會與輸入框的內容同步變化:

深入理解vue.js雙向綁定的實作原理

七、訂閱/發布模式(subscribe

七、訂閱/發布模式(subscribe

)方法變化了觸發了,但是文字節點的內容沒有改變。如何讓同樣綁定到text的文字節點也同步變化呢?這裡又有一個知識點:訂閱發布模式。

訂閱發布模式(又稱觀察者模式)定義了一種一對多的關係,讓多個觀察者同時監聽某一個主題對象,這個主題對象的狀態改變時就會通知所有觀察者對象。

深入理解vue.js雙向綁定的實作原理發布者發出通知=> 主題對象收到通知並推送給訂閱者=> 訂閱者執行相應操作

之前提到的,當set方法觸發後做的第二件事就是作為發布者發出通知:「我是屬性text,我變了」。文字節點則是作為訂閱者,在收到訊息後執行對應的更新操作。

八、雙向綁定的實作

回顧一下,每當new一個Vue,主要做了兩件事:第一個是監聽資料:observe(data) ,第二個是編譯HTML:nodeToFragement(id) 。

在監聽資料的過程中,會為data中的每一個屬性產生一個主題物件dep。

在編譯HTML的過程中,會為每個與資料綁定相關的節點產生一個訂閱者watcher,watcher會將自己加入對應屬性的dep中。

我們已經實作:修改輸入框內容 => 在事件回呼函數中修改屬性值 => 觸發屬性的set方法。

接下來我們要實現的是:發出通知dep.notify() => 觸發訂閱者的update方法 => 更新視圖。

深入理解vue.js雙向綁定的實作原理這裡的關鍵邏輯是:如何將watcher加入關聯屬性的dep。

深入理解vue.js雙向綁定的實作原理在編譯HTML過程中,為每個與data關聯的節點​​產生一個Watcher。 Watcher函數中發生了什麼事?

首先,將自己賦給了一個全域變數Dep.target;

其次,執行了update方法,進而執行了get方法,get的方法讀取了vm的存取器屬性,從而觸發了存取器屬性的get方法,get方法中將該watcher加入了對應存取器屬性的dep中;

再次,取得屬性的值,然後更新視圖。

深入理解vue.js雙向綁定的實作原理最後,將Dep.target設為空。因為它是全域變量,也是watcher與dep相關的唯一橋樑,任何時刻都必須保證Dep.target只有一個值。

深入理解vue.js雙向綁定的實作原理

🎜🎜🎜

深入理解vue.js雙向綁定的實作原理

至此,hello world雙向綁定就基本實現了。文字內容會隨輸入框內容同步變化,在控制器中修改vm.text的值,會同步反映在文字內容中。

總結

以上就是關於vue.js雙向綁定實現原理的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對PHP中文網的支援。

更多深入理解vue.js雙向綁定的實作原理相關文章請關注PHP中文網!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn