vue&react源碼思考之:雙向綁定

作者:心葉
時間:2019-07-18 10:34

本文章構思的實現方法在github上有對應的項目已經實現,項目依舊在不斷改進中:abandon.js

核心方法說明

Object.defineProperty(obj,key,{
    get(){
        // todo1
    },
    set(newValue){
        // todo2
    }
});

比如obj是一個json,其有一個值key,也就是obj.key。我們可以通過上面的方法對設置和獲取obj.key的時候進行攔截處理,而這就是js部分雙向綁定的核心。

設計思路

頁面 → JS

監聽輸入框的輸入時間,如果有輸入,就主動改變js中的值,這樣,頁面到js這一條路就通了。

JS → 頁面

js部分通過前面說的Object.defineProperty方法,對需要雙向綁定的數據進行攔截,發現數據改變的時候,就主動去修改頁面顯示,這樣,js到頁面這一條路就通了。

難點

上面的說明看起來很簡單,然而,事實並非如此,主要有下面幾個問題(其實主要是設計的問題):

  • js數據改變了,你怎麼知道應該修改頁面中哪些地方?
  • 頁面的表達式可能很複雜,如何解析
  • 數組或對象如何監聽

實現

主體對象

控制整個流程,餘下的都是由這裏協調資源。

let Abandon = function (options) {

    // 管理的數據(雙向綁定)
  this._data = options.data || {};
    
   // 對維護的數據進行監聽
  this.__observe();

  // 獲取掛載點
  this.$el = $$(options.el)[0];
  
  // 編譯結點
  this.__compile();

}

數據攔截者observe.js

對象options的data中定義的key的編輯會在這裏攔截,通知專門處理變化情況的(同步視圖和數據)。

export default function(){

    for (let key in this._data) {
    
    // 定義攔截鉤子
    Object.defineProperty(this._data, key, {
         get() {
            // todo
          },
          set(newValue) {
             // todo
          }
    });
    
};

編譯程序compile.js

簡單點說,就是分析結點中的內容,有沒有定義的指令等,根據結點內容追加需要管理的東西。

export default function(){

    let nodes = this.$el.childNodes;
    
    for (let i = 0; i < nodes.length; i++) {
        
        // 如果不是文本結點,繼續編譯
      if (node.nodeType !== 3) {
        // todo
      }
      
      // 開始正式解析一個結點(分爲文本結點和非文本結點)
      // 解析的意思就是標記需要管理的屬性,文本等
      if (node.nodeType === 3) {
        // 如果是文本

      } else {
        // 如果不是文本
        
        }
        
    }
    
};

後記

上面力求簡單,具體的代碼沒有顯示出來,如果需要看具體代碼,請去github/abandon.js上查看。

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