vue實現數據驅動視圖原理

1、什麼是數據驅動

  數據驅動是vuejs最大的特色。在vuejs中,所謂的數據驅動就是當數據發生變化的時候,用戶界面發生相應的變化,開發者不須要手動的去修改dom。javascript

  好比說咱們點擊一個button,須要元素的文本進行是和否的切換。在jquery刀耕火種的年代中,對於頁面的修改咱們通常是這樣的一個流程,咱們對button綁定事件,而後獲取文案對應的元素dom對象,而後根據切換修改該dom對象的文案值。而對於vuejs實現這個功能的流程,只須要在button元素上指明事件,同時聲明對應文案的屬性,點擊事件的時候改變屬性的值,對應元素的文本就可以自動的進行切換,咱們不須要像之前那樣手動的操做dom。前端

  簡而言之,就是vuejs幫咱們封裝了數據和dom對象操做的映射,咱們只須要關心數據的邏輯處理,數據的變化就可以天然的通知頁面進行頁面的從新渲染vue

  這樣作的確實給咱們帶來的好處,咱們不須要再在代碼中頻繁地去操做dom了,在實際項目中,咱們有很大部分代碼都是在數據修改之後,手動操做從新渲染頁面元素,當頁面愈來愈複雜的時候,頁面代碼組織會越來難以維護。同時,js對dom的頻繁操做,會使得頁面代碼的出錯機率高,頁面的視圖展現會融合在js代碼中,對於頁面視圖顯示的升級也不友好。java

  那麼vuejs是如何實現這種數據驅動的呢?jquery

2、MVVM框架

  Vuejs的數據驅動是經過MVVM這種框架來實現的。MVVM框架主要包含3個部分:model、view和 viewmodel。app

  Model:指的是數據部分,對應到前端就是javascript對象框架

  View:指的是視圖部分,對應前端就是domdom

  Viewmodel:就是鏈接視圖與數據的中間件函數

  數據(Model)和視圖(View)是不能直接通信的,而是須要經過ViewModel來實現雙方的通信。當數據變化的時候,viewModel可以監聽到這種變化,並及時的通知view作出修改。一樣的,當頁面有事件觸發時,viewModel也可以監聽到事件,並通知model進行響應。spa

  Viewmodel就至關於一個觀察者,監控着雙方的動做,並及時通知對方進行相應的操做。

3、Vuejs的數據驅動實現

  對於數據驅動的實現,咱們能夠簡單的經過定時器來實現這個功能,定時器定時監控對象數據,定時器監控數據變化,肯定是否更新界面

var a = 1; function renderDom() { document.getElementById('app').innerHTML = '數據是' + a; } function watcher(method) { var b = a; method.apply(); return setInterval(function() { if (b != a) { method.apply(); b = a; } }, 1000) } watcher(renderDom);

  固然vuejs不多是這樣簡單暴力的實現方式,vuejs是經過在實現一個觀察者來實現的數據驅動。

  首先,vuejs在實例化的過程當中,會遍歷傳給實例化對象選項中的data 選項,遍歷其全部屬性並使用 Object.defineProperty 把這些屬性所有轉爲 getter/setter。

  同時每個實例對象都有一個watcher實例對象,他會在模板編譯的過程當中,用getter去訪問data的屬性,watcher此時就會把用到的data屬性記爲依賴,這樣就創建了視圖與數據之間的聯繫。當以後咱們渲染視圖的數據依賴發生改變(即數據的setter被調用)的時候,watcher會對比先後兩個的數值是否發生變化,而後肯定是否通知視圖進行從新渲染。

  這樣就實現了所謂的數據對於視圖的驅動。通俗地講,它意味着咱們在普通 HTML 模板中使用特殊的語法將 DOM 「綁定」到底層數據。一旦建立了綁定,DOM 將與數據保持同步。每當修改了數據,DOM 便相應地更新。這樣咱們應用中的邏輯就幾乎都是直接修改數據了,沒必要與 DOM 更新攪在一塊兒。這讓咱們的代碼更容易撰寫、理解與維護。

  對getter/setter的理解
  當打印出Vue實例下的data對象裏的屬性,它的每一個屬性都有兩個相對應的get和set方法。正常狀況下,咱們取值和賦值是用obj.prop的方式,可是這樣作有一個問題,我如何知道對象的值改變了?因此就輪到set登場了。
  你能夠把get和set理解爲function,當咱們調用對象的屬性時,咱們會進入到get.屬性(){...}中,先判斷對象是否有這個屬性,若是沒有,那麼就添加一個name屬性,並給它賦值;若是有name屬性,那就返回name屬性。你能夠把get當作一個取值的函數,函數的返回值就是它拿到的值。
  感受比較重要的是set屬性,當給實例賦值:此時,會進入set name(val){...};形參val就是我賦給name屬性的值,在這個函數裏,就能夠作不少事了,好比雙向綁定!由於這個值的每次改變都必須通過set,其餘方式是改變不了它的,至關於一個萬能的監聽器。ES5的對象原型有兩個新的屬性__defineGetter__和__defineSetter__,專門用來給對象綁定get和set。建議使用下面這種方式,由於是在原型上書寫,因此能夠繼承和重用。
相關文章
相關標籤/搜索