Vue雙向數據綁定的理解

一、什麼是MVVM框架

   所謂MVVM,是Model - View - ViewModel 的簡寫。

   我的理解是

頁面上所看到的就是View。
使用Vue.js或者是其他MVVM框架,是在操作ViewModel,實現View - ViewModel的雙向互動。
然後Model就是服務器的資源,ViewMdoel從服務器請求數據,或者發送數據給服務器,就是ViewModel - Model的雙向互動。

二、雙向數據綁定的原理

    雙向數據綁定,雙向指的是兩個方向。

    一是數據驅動頁面,

    二是頁面改動了,會響應式的改變綁定的數據。主要是input的變動。

    綁定說的是MVVM框架,自動的去完成數據的改動,頁面的渲染。

    不像以前,改變頁面上的一個值,要先去獲取該元素的節點,然後再去設置它的文本內容(比如innerHTML屬性)。

    那麼更具體的講,具體實現主要使用的是,或者說細節是:

    1.Object.defineProperty屬性。這是MVVM框架的核心API。

    2.觀察者設計模式

    利用Object.defineProperty這個API實現了對Data每個屬性的監聽和回調。

    數據驅動頁面方向:就是當去修改Data某一個屬性時,會通知觀察者,然後觀察者觸發自身的回調函數,進而重新渲染頁面。

    頁面 =》 數據:其實就是去監聽input的oninput事件。oninput事件會去修改對應的Data的屬性值。


三、淺談Vue框架實現響應式的原理。

    前面說過,雙向數據綁定的核心是Object.definePrototype這個API,Vue的響應式主要做了四方面的工作。

    1.通過Object.definePrototype,劫持了Vue實例對象中的data屬性下的每一個值,並設置了相應的getter和setter。

   2.實現了一個compile解析器,將Vue實例對象的el屬性掛載的DOM節點下的所有節點進行解析。類似於全部銷燬,然後創建一個文檔碎片fragment,將識別到的特殊的節點做特殊處理,在放入文檔碎片fragment中,最後再講文檔碎片fragment放進根節點,也就是掛載的元素中。

   3.實現了一個觀察者watcher,自身有一個updata方法,當數據修改的時候,就會通知觀察者調用updata方法,去將相應節點的textContent更新。

   4.實現了一個消息訂閱器Dep,用來接收觀察者的訂閱,並在數據修改時通知觀察者。

那麼以上觀察者如何在Dep中訂閱消息,怎麼實現這是一個難點。

   簡單的說,我的理解。

  參考了一篇文章,

  比如當compile解析器解析到{{message}}這樣子的文本節點的時候,就可以認爲這個地方綁定了一個變量,就可以實例化一個觀察者。看到觀察者的代碼,

 /*
  	變量的含義:
  	vm:Vue實例對象
  	node:變量所在的文本節點(就是{{message}})
  	name:綁定的變量名(就是message)
    */
    function Watcher(vm,node,name){
        //讓全局變量Dep的target屬性的指針指向該watcher實例
        Dep.target = this;
        this.vm = vm;
        this.node = node;
        this.name = name;
        //放入Dep.target才能update()?????????????????????????????????????????
        this.update();
        Dep.target = null;
    }
    // 觀察者使用update方法,實際上是
    Watcher.prototype = {
        update: function(){
            this.get();
            this.node.nodeValue = this.value;
        },
        //獲取data中的屬性值 
        get: function(){
            this.value = this.vm[this.name]; //觸發相應屬性的get
        }
    }
然後在getter中這樣定義
 get: function(){
      //Dep.target指針指向watcher,增加訂閱者watcher到主體對象Dep
      if(Dep.target){
         dep.addSub(Dep.target);
      }
      return val;
因爲在實例化watcher的時候,會執行watcher的updata方法,updata方法中又執行了watcher的get方法,get方法會訪問到message屬性,觸發對應的getter,就會往訂閱器Dep中添加watcher。


  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章