幾種實現雙向綁定的作法:vue
目前幾種主流的mvc(vm)框架都實現了單項數據綁定,而我所理解的雙向數據綁定,無非就是在單項數據綁定的基礎上給輸入元素input textare等添加了change(input)事件,來動態修改model和view,並無多高深。因此無須介懷是實現的單項或者雙向綁定,實現數據綁定 大體幾種:算法
- 發佈者-訂閱者(backbone.js);
- 通常經過sub,pub的方式實現數據和視圖的綁定監聽,更新數據的方式一般是 vm.set('property',vlue);
- 髒值檢查(angular.js);
- Angular.js是經過髒值檢測的方式比對數據是否有變動。來決定是否更新視圖,最簡單方式是經過setinterval()定時輪詢檢測數據變更,固然angular只是在指定的事件觸發時進入髒值檢測:
- Ng-click
- $http
- $location
- $timeout $interval
- $digest()||$apply()
- 數據劫持(vue.sj);
Vue.js則採用數據劫持+發佈者訂閱者模式的方式,經過0bject.defineProperty()來劫持各個屬性的setter getter,在數據發生改變時發佈消息給訂閱者,觸發相應的監聽回調。具體整理:數組
vue是經過數據劫持的方式來作數據綁定,其中核心方法是經過object,defineProperty()來實現對屬性的劫持,達到監聽數據變更的目的,無疑這個方法是本文中最重要,最基礎的內容之一。瀏覽器
Object.defineProperty()直接在一個對象上定義一個新的屬性,或者修改一個對象的現有屬性,並返回這個對象。mvc
實現mvvm雙向數據綁定,步驟:app
- 實現一個數據監聽observer(觀察者),可以對數對象的全部屬性進行監聽,若是有變更可拿到最新值並通知訂閱者;
- 利用object.defineProperty()來監聽屬性變更;那麼將須要observer的數據對象進行遍歷,包括子屬性對象的屬性,都加上setter和getter這樣的話給這個對象的某個值賦值,就會觸發setter,從我的監聽到數據變化。
- 監聽到後,怎末通知訂閱者呢?因此須要實現一個消息訂閱器:維護一個數組,用來手機訂閱者,數據變更會觸發notify,再調用訂閱者的update方法。watcher
- 實現一個指令解析器Compile,對每一個元素的指令進行進行掃描和解析,根據指令模板替換數據,以及綁定相應數據;
- complile解析模板指令,將模板中的變量替換成數據,而後初始化渲染頁面視圖,並將每一個指令對應的節點綁定跟新函數,方便隨時更新視圖。
- 由於遍歷解析的過程有屢次dom節點,爲了提升性能和效率,會先將節點el轉換爲文檔碎片進行解析編譯(js對象虛擬DOM),解析完成後再添加回原來的真實dom節點中。
- 實現watcher,做爲鏈接observer和compile的橋樑,可以訂閱並收到每一個屬性變更的通知,執行指令綁定相應的會回調函數,從而跟新試圖。
- 在自身實例化時往屬性訂閱器dep裏面添加本身;
- 自身必須有一個update()方法;
- 代屬性變更dep.notice()通知時,能調用自身的update()方法,並觸發complie中綁定的回調.
- mvvm入口函數,整合以上三者;達到數據變化-》視圖更新;視圖交互變化(input)->數據model變動的雙向數據綁定效果;
MVVM:model view view model框架
數據雙向綁定,簡化了頁面和業務的依賴,解決了數據頻繁更新。MvvM在使用當中,利用雙向數據綁定計數,使得Model變化時,viewModel 會自動更新,而viewModel 變化時,view也會自動變化。dom
雙向數據綁定原理:mvvm
採用數據劫持:發佈者和訂閱者模式的方式,經過object.defineProperty()來劫持各個屬性的setter和getter,在數據變更時發佈消息給訂閱者,出發相應的監聽回調;具體步驟:函數
- 當把一個普通的js對象傳給VUE實例來做爲他的data選項時,vue將遍歷他的屬性,用object.defineProperty都加上setter和getter方法,這樣給這個對象的某個值賦值,就會出發setter,那麼就能監聽到數據變化;
- compile解析模板指令
- Watcher 訂閱者是observer和compile之間的橋樑,主要作的事:
- 在自身實例化時往屬性訂閱器(dep)裏添加本身;
- 子集必須有一個update()方法
- 待屬性變更dep.notice通知時,調取update()方法,並觸發compile綁定的回調,則功成身退。
- MvvM做爲數據的綁定入口,整合observer compile watcher三者:
- 經過observer來監聽本身的model數據變化;
- 經過compile來解析編譯模板指令
- 最終利用wacher搭起observer和compile之間的通訊橋樑,
- 達到數據變化=>視圖跟新;視圖交互變化(input)=>數據model變動的雙向數據效果。
proxy相比defineProperty優點:
Object.defineProperty()三個主要問題:
- 不能監聽數組變化;
- 必須遍歷對象的每一個屬性;
- 必須生層次遍歷嵌套的對象;
而 ES5的proxy新加入,特色:
- 針對對象:針對整個對象而不是對象的某個屬性,因此也就不須要keys進行遍歷
- 支持數組:proxy不須要對數組進行重載,省去了衆多hack,減小代碼等於減小維護成本。
vue中的虛擬DOM:
虛擬DOM本質就是一個和真實DOM結構相似的Js對象;
虛擬DOM能夠提升瀏覽器的渲染速度。對比操做Js對象,比操做真實的DOM消耗的性能少的多,特別時 頻繁的操做DOM時,優點彰顯的更加明顯。
虛擬DOM步驟:
- 在頁面首次渲染時,將要渲染的數據所有加載到虛擬DOM中,然後在一次性渲染到真實的DOM上;
- 數據變更時,額外生成一個虛擬DOM樹,
- 經過Diff算法對比修改的部分,然後將修改部分渲染到真實的DOM中;
- 釋放內存。