Vue元件

寒青發表於2018-01-19

元件系統

元件可以擴充套件 HTML 元素,封裝可重用的程式碼。

vue.js的核心元件:

  1. 模板(template)——模板宣告瞭資料和最終展現給使用者的DOM之間的對映關係。
  2. 初始資料(data)——一個元件的初始資料狀態。對於可複用的元件來說,通常是私有的狀態。
  3. 接受的外部引數(props)——元件之間透過引數來進行資料的傳遞和共享。引數預設是單向繫結(由上至下),但也可以顯式宣告為雙向繫結。
  4. 方法(methods)——對資料的改動操作一般都在元件的方法內進行。可以透過v-on指令將使用者輸入事件和元件方法進行繫結。
  5. 生命週期鉤子函式(lifecycle hooks)——一個元件會觸發多個生命週期鉤子函式,比如createdattacheddestroyed等。在這些鉤子函式中,我們可以封裝一些自定義的邏輯。和傳統的MVC相比,這可以理解為Controller的邏輯被分散到了這些鉤子函式中。
  6. 私有資源(assets):Vue.js當中將使用者自定義的指令過濾器元件等統稱為資源。由於全域性註冊資源容易導致命名衝突,一個元件可以宣告自己的私有資源。私有資源只有該元件和它的子元件可以呼叫。
  7. 除此之外,同一棵元件樹之內的元件之間還可以透過內建的事件API來進行通訊。Vue.js提供了完善的定義、複用和巢狀元件的API,讓開發者可以像搭積木一樣用元件拼出整個應用的介面。這個思路的可行性在Facebook開源的React當中也得到了印證。

基於構建工具的單檔案元件格式

Vue.js的核心庫只提供基本的API,本身在如何組織應用的檔案結構上並不做太多約束。但在構建大型應用時,推薦使用 Webpack+vue-loader 這個組合以使針對元件的開發更高效。

Webpack是由Tobias Koppers開發的一個開源前端模組構建工具。它的基本功能是將以模組格式書寫的多個JavaScript檔案打包成一個檔案,同時支援CommonJS和AMD格式。但讓它與眾不同的是,它提供了強大的loader API來定義對不同檔案格式的預處理邏輯,從而讓我們可以將CSS、模板,甚至是自定義的檔案格式當做JavaScript模組來使用。Webpack 基於loader還可以實現大量高階功能,比如自動分塊打包並按需載入對圖片資源引用的自動定位根據圖片大小決定是否用base64內聯開發時的模組熱替換等等,可以說是目前前端構建領域最有競爭力的解決方案之一。

其他特性

Vue.js還有幾個值得一提的特性:

  1. 非同步批次DOM更新:當大量資料變動時,所有受到影響的watcher會被推送到一個佇列中,並且每個watcher只會推進佇列一次。這個佇列會在程序的下一個 “tick” 非同步執行。這個機制可以避免同一個資料多次變動產生的多餘DOM操作,也可以保證所有的DOM寫操作在一起執行,避免DOM讀寫切換可能導致的layout。
  2. 動畫系統:Vue.js提供了簡單卻強大的動畫系統,當一個元素的可見性變化時,使用者不僅可以很簡單地定義對應的CSS TransitionAnimation效果,還可以利用豐富的JavaScript鉤子函式進行更底層的動畫處理。
  3. 可擴充套件性:除了自定義指令過濾器元件,Vue.js還提供了靈活的mixin機制,讓使用者可以在多個元件中複用共同的特性。

使用Prop傳遞資料

元件例項的作用域是孤立的。這意味著不能(也不應該)在子元件的模板內直接引用父元件的資料。要讓子元件使用父元件的資料,我們需要透過子元件的 props 選項。

子元件要顯式地用 props 選項宣告它期待獲得的資料。

Vue.component({
        props: ['message'],
        template: '<span>{{message}}</span>'
    });

父子元件通訊

Vue 中子元件可以透過透過事件和父元件進行通訊的。向父元件發訊息是透過 this.$dispatch,而向子元件傳送訊息是透過 this.$boardcast

資料繫結的實現原理

Vue 把雙向繫結稱作 reactive,可以翻譯為響應式資料繫結。內部是透過 ES5 定義的 gettersetter 方法實現的,所以不支援 IE8 及以下瀏覽器,這種實現方式有兩個容易犯錯的地方:

  • 如果在 data 上直接新增和刪除屬性是無法被檢測到的,一般刪除是不會的,但是可能會動態新增,這個時候應該透過 vm.$set(“name”, value) 的方式來新增。
  • 無法檢測到物件內部的變化,也就是隻能檢測 data 的屬性變化,如果 data.a 是一個物件,那麼 data.a.b = 1 這種變化是無法被檢測到的。這種情況下應該建立一個新的物件並賦值給 data.a 就行了。

非同步更新機制

Vue 對DOM的更新是非同步的! 這個非同步是在一個非同步佇列中進行的,不過這個非同步佇列會在當前的 Event Loop 中執行完,所以如果修改了 Data 立刻去DOM中做查詢操作是不對的,這個時候DOM還沒有更新,正確的做法是這樣做:

vm.msg = 'new message' // change data
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
 vm.$el.textContent === 'new message' // true
})

或者這樣:

vm.$nextTick(function () {
 this.$el.textContent === 'new message' // true
})

相關文章