雙向數據綁定原理

幾種實現雙向綁定的作法:vue

    目前幾種主流的mvc(vm)框架都實現了單項數據綁定,而我所理解的雙向數據綁定,無非就是在單項數據綁定的基礎上給輸入元素input textare等添加了change(input)事件,來動態修改model和view,並無多高深。因此無須介懷是實現的單項或者雙向綁定,實現數據綁定 大體幾種:算法

  1. 發佈者-訂閱者(backbone.js);
    1. 通常經過sub,pub的方式實現數據和視圖的綁定監聽,更新數據的方式一般是  vm.set('property',vlue);

 

  1. 髒值檢查(angular.js);
    1. Angular.js是經過髒值檢測的方式比對數據是否有變動。來決定是否更新視圖,最簡單方式是經過setinterval()定時輪詢檢測數據變更,固然angular只是在指定的事件觸發時進入髒值檢測:
      1.   
      2. Ng-click
      3.   
      4. $http
      5.   
      6. $location
      7.   
      8. $timeout $interval
      9.   
      10. $digest()||$apply()
  2. 數據劫持(vue.sj);

Vue.js則採用數據劫持+發佈者訂閱者模式的方式,經過0bject.defineProperty()來劫持各個屬性的setter  getter,在數據發生改變時發佈消息給訂閱者,觸發相應的監聽回調。具體整理:數組

vue是經過數據劫持的方式來作數據綁定,其中核心方法是經過object,defineProperty()來實現對屬性的劫持,達到監聽數據變更的目的,無疑這個方法是本文中最重要,最基礎的內容之一。瀏覽器

Object.defineProperty()直接在一個對象上定義一個新的屬性,或者修改一個對象的現有屬性,並返回這個對象。mvc

實現mvvm雙向數據綁定,步驟:app

  1. 實現一個數據監聽observer(觀察者),可以對數對象的全部屬性進行監聽,若是有變更可拿到最新值並通知訂閱者;
    1. 利用object.defineProperty()來監聽屬性變更;那麼將須要observer的數據對象進行遍歷,包括子屬性對象的屬性,都加上setter和getter這樣的話給這個對象的某個值賦值,就會觸發setter,從我的監聽到數據變化。
    2. 監聽到後,怎末通知訂閱者呢?因此須要實現一個消息訂閱器:維護一個數組,用來手機訂閱者,數據變更會觸發notify,再調用訂閱者的update方法。watcher
  2. 實現一個指令解析器Compile,對每一個元素的指令進行進行掃描和解析,根據指令模板替換數據,以及綁定相應數據;
    1. complile解析模板指令,將模板中的變量替換成數據,而後初始化渲染頁面視圖,並將每一個指令對應的節點綁定跟新函數,方便隨時更新視圖。
    2. 由於遍歷解析的過程有屢次dom節點,爲了提升性能和效率,會先將節點el轉換爲文檔碎片進行解析編譯(js對象虛擬DOM),解析完成後再添加回原來的真實dom節點中。
  3. 實現watcher,做爲鏈接observer和compile的橋樑,可以訂閱並收到每一個屬性變更的通知,執行指令綁定相應的會回調函數,從而跟新試圖。
    1. 在自身實例化時往屬性訂閱器dep裏面添加本身;
    2. 自身必須有一個update()方法;
    3. 代屬性變更dep.notice()通知時,能調用自身的update()方法,並觸發complie中綁定的回調.
  4. mvvm入口函數,整合以上三者;達到數據變化-》視圖更新;視圖交互變化(input)->數據model變動的雙向數據綁定效果;

 

 

 

 

 

 

 

 

MVVM:model   view   view model框架

數據雙向綁定,簡化了頁面和業務的依賴,解決了數據頻繁更新。MvvM在使用當中,利用雙向數據綁定計數,使得Model變化時,viewModel  會自動更新,而viewModel 變化時,view也會自動變化。dom

 

雙向數據綁定原理:mvvm

採用數據劫持:發佈者和訂閱者模式的方式,經過object.defineProperty()來劫持各個屬性的setter和getter,在數據變更時發佈消息給訂閱者,出發相應的監聽回調;具體步驟:函數

  1. 當把一個普通的js對象傳給VUE實例來做爲他的data選項時,vue將遍歷他的屬性,用object.defineProperty都加上setter和getter方法,這樣給這個對象的某個值賦值,就會出發setter,那麼就能監聽到數據變化;
  2. compile解析模板指令
  3. Watcher 訂閱者是observer和compile之間的橋樑,主要作的事:
    1. 在自身實例化時往屬性訂閱器(dep)裏添加本身;
    2. 子集必須有一個update()方法
    3. 待屬性變更dep.notice通知時,調取update()方法,並觸發compile綁定的回調,則功成身退。
    4. MvvM做爲數據的綁定入口,整合observer compile watcher三者:
      1.   
      2. 經過observer來監聽本身的model數據變化;
      3.   
      4. 經過compile來解析編譯模板指令
      5.   
      6. 最終利用wacher搭起observer和compile之間的通訊橋樑,
      7.   
      8. 達到數據變化=>視圖跟新;視圖交互變化(input)=>數據model變動的雙向數據效果。

 

proxy相比defineProperty優點:

Object.defineProperty()三個主要問題:

  1. 不能監聽數組變化;
  2. 必須遍歷對象的每一個屬性;
  3. 必須生層次遍歷嵌套的對象;

而  ES5的proxy新加入,特色:

  1. 針對對象:針對整個對象而不是對象的某個屬性,因此也就不須要keys進行遍歷
  2. 支持數組:proxy不須要對數組進行重載,省去了衆多hack,減小代碼等於減小維護成本。

 

vue中的虛擬DOM:

          虛擬DOM本質就是一個和真實DOM結構相似的Js對象;

        虛擬DOM能夠提升瀏覽器的渲染速度。對比操做Js對象,比操做真實的DOM消耗的性能少的多,特別時                             頻繁的操做DOM時,優點彰顯的更加明顯。

 虛擬DOM步驟:

  1.  在頁面首次渲染時,將要渲染的數據所有加載到虛擬DOM中,然後在一次性渲染到真實的DOM上;
  2. 數據變更時,額外生成一個虛擬DOM樹,
  3. 經過Diff算法對比修改的部分,然後將修改部分渲染到真實的DOM中;
  4. 釋放內存。
相關文章
相關標籤/搜索