第231期 / January 5, 2017

研發新視界

分享到臉書!分享到維特!分享到噗浪!分享到Google+!分享到微博!轉寄友人友善列印

深入淺出談 Vue.js

作者/沈慧翰

[發表日期:2017/1/5]

vue 是什麼

Vue.js是一個構建web 界面的library。 Vue.js 的目標是通過盡可能簡單的 API 實現響應的數據綁定和組合的視圖組件。響應的數據綁定就是數據驅動視圖的概念。它讓你在寫 Web 應用介面時,只需要關注兩件事:數據如何展示和數據如何變化。一旦數據發生變化時,比如用戶輸入,或者 ajax 請求返回後數據發現修改,對應的視圖介面會自動的進行更新。Vue.js 重點集中在MVVM模式的ViewModel層。因此它非常容易學習,非常容易與其它library或已有項目整合。另一方面,在與相關工具一起使用時,Vue.js 也能完美地操作複雜的應用。

MVVM 數據綁定

Vue.js在數據綁定的API設計上可以通過具有特殊前綴的HTML 屬性來實現數據綁定,也可以使用常見的大括號模板插入變數,或是在表單元素上使用雙向綁定;Vue.js會為每一處需要動態更新的DOM節點創建一個指令對象。每當一個指令對象觀測的數據變化時,它便會對所綁定的目標節點執行相應的DOM操作。基於指令的數據綁定使得具體的DOM操作都被合理地封裝在指令定義中,業務代碼只需要涉及模板和對數據狀態的操作即可,這使得應用的開發效率和可維護性都大大提升。


《圖一》Vue.js的MVVM架構


Vue 響應式原理探析

一、Vue 的基礎 — getter/setter

Vue 使用的方法實現了雙向綁定如下:

Vue.js利用了ES5的Object.defineProperty方法,直接將原生數據對象的屬性改造為getter和setter,在這兩個函數內部實現依賴的收集和觸發,而且完美支持嵌套的對象結構。這是 ES5 特性。getter/setter 使得開發者有機會在對象屬性取值和賦值的時候進行自定義操作,響應系統便是基於這個特性實現的。

二、Vue的 核心 — Watcher

不只是Model中的指令和數據綁定,計算屬性也是由 watcher 來實現的,Model中每個指令/數據綁定都有一個對應的 watcher,在計算過程中屬性標示為依賴。之後當依賴的setter被使用時,會觸發 watcher 重新計算,也因此就會更新 DOM。


《圖二》Vue.js的數據綁定


三、依賴收集

Watcher 和數據項之間的依賴關係是一個多對多的關係, Vue 就是依靠靠著依賴收集管理 Watcher 和數據項之間的依賴關係。

依賴收集是通過 property 的getter完成的,依賴收集的過程涉及到 Vue 的三類對象:Watcher、Dep 和 Observer。其中 Observer 負責將數據項轉化為響應式對象,而 Dep 則用來描述 Watcher 和 Observer 的依賴關係。Vue 中,每個 Observer 對應一個 Dep 對象,而每個 Dep 對象可以對應多個 Watcher,每個 Watcher 也可以對應多個 Dep 對象,從而實現了多對多的依賴關係。

Vue 實例初始化的過程中,首先,每個數據項都會生成一個 Observer,每個 Observer 又會初始化一個 Dep 實例;接下來,模板中的每個指令和數據綁定都會生成一個 Watcher 實例,實例化的過程中,會計算這個 Watcher 對應表達式的值;計算開始之前,Watcher 會設置 Dep 的靜態屬性 Dep.target 指向其自身,開始依賴收集;計算表達式的過程中,該 Watcher 依賴的數據項會被訪問,從而觸發其getter中的程式碼;數據項getter中會判斷 Dep.target 是否存在,若存在則將自身的 Dep 實例保存到 Watcher 的列表中,並在此 Dep 實例中註冊 Watcher;重複上述過程直至 Watcher 計算結束,Dep.target 被清除,依賴收集完成。

以下就是完成響應的整個過程。在依賴關係建立後,每當setter被訪問時,Observer 會調用其Dep 實例的notify 方法,在這個Dep 實例中註冊的Watcher 將會被通知並重新進行計算及依賴收集的過程,然後執行相應的回調函數。

四、Vue.js特性:

  • 異步批量DOM更新:當大量數據變動時,所有受到影響的watcher會被推送到一個隊列中,並且每個watcher只會推進隊列一次。這個隊列會在進程的下一個 「tick」 異步執行。這個機制可以避免同一個數據多次變動產生的多餘DOM操作,也可以保證所有的DOM寫操作在一起執行。


  • 動畫系統:Vue.js提供了簡單卻強大的動畫系統,當一個元素的可見性變化時,用戶不僅可以很簡單地定義對應的CSS Transition或Animation效果,還可以利用豐富的JavaScript函數進行更底層的動畫處理。


  • 可擴展性:除了自定義指令、過濾器和組件,Vue.js還提供了靈活的mixin機制,讓用戶可以在多個組件中複用共同的特性。


  • 實例


    《圖三》


    簡單來說{{}}就是會幫你帶參數進去這個位置上,而在new Vue指定在id名稱為app的這個element裡帶進message參數,而message我在這裡指定預設值為Hello World! ,以上就是示範Hellow world的寫法。


    《圖四》


    將{{message}} 加上h1標籤,然後在下方新增一個文字的input輸入表單,接著v-model名稱是message,所以這個input就會自動帶入與{{message}} 相同的參數內容,而只要變更inupt裡面的文字,頁面上的{{message}}參數也會立刻馬上一起更新,當v-model裡面輸入文字或刪減文字時,修改的其實就是data裡面message的參數值,既然參數值改變,vue.js就會自動幫你啟動model進而修改{{message}} 在頁面上呈現的內容,進而達到Real-time即時更新頁面的效果。


    《圖五》


    上面的範例程式碼,加上了score預設值是0,然後當score是有值的,就會根據目前輸入的分數去做判斷,判斷內容就是大於等於6分以上就會顯示“Pass”,不足6分就會顯示“fail”。

    html 擴充屬性:

  • v-show :Vue.js特有的寫法,等於v-if,所以屬性質就是所謂的運算條件了。


  • v-else : 當v-show或v-if條件不成立時需要選擇的答案。


  • Vue 的優點&缺點

    一、優點:

  • 快速學習,快速開發,維護簡單。

  • life cycle 跟 component 宣告的方式與 React 很像,如果有學過 React 會很快就上手 vue。

  • 豐富的套件,舉凡 Routing, I18n, UI, StateManage 等等都有第三方套件,幾乎是 react 有的 vue 也有。

  • 可以限制 CSS 作用的區域。


  • 二、缺點:

  • Vue 的缺點就是目前只能做web,不能像React一樣跨到native app,第二就是社群大小是 React 略勝一籌。


  • 總結

    在發佈之初,Vue.js原本是著眼於輕量的嵌入式使用場景。由於其輕量、高性能的特點,對於移動場景也有很好的契合度。更重要的是,設計完備的組件系統和配套的構建工具、插件,與Angular相似的指令,與React相似的模塊化處理。然而Vue和它們明顯不同,它更加輕量,易於上手,你不需要像Angular那樣去進行複雜的配置,也不需要像React那樣去學習新的虛擬DOM、JSX等等新的概念。使得Vue.js在保留了其簡潔API的同時,也已經完全有能力擔當起複雜的大型應用的開發。因此,如果你的應用並不是很龐大,不妨考慮用Vue作為應用框架。

    參考資料

    https://vuejs.org.cn/guide/
    http://www.itdadao.com/articles/c15a371166p0.html
    http://zjy.name/archives/vue-reactive-study.html