理解
組件(Component)是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素, Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以是原生 HTML 元素的形式,以 is 特性擴展。
使用組件
創建單文件組件
<template>
</template>
<script>
export default {
};
</script>
<style lang="stylus" rel="stylesheet/stylus">
</style>
組件注冊
注冊分為兩種:局部注冊和全局注冊。注冊一個全局組件,可以使用 Vue.component(tagName, options)。 把構造函數注冊到my-component這個 id Vue.component('my-component', MyComponent),為了寫法更簡單,也可以直接傳入 option 對象來代替構造函數,Vue.component() 會為你隱式調用 Vue.extend() 。
// 注冊全局組件,指定之前設定的元素名,然后傳入對象
Vue.component('my-component', {
template: '<div>hello world!</div>'
})
之后就能在父級實例的模板中使用注冊過的組件了 (務必在初始化根實例之前注冊組件) :
<my-component></my-component>
我們沒有必要,也不應該全局注冊所有組件。你可以限制一個組件僅對另一個組件及其后代可用,只要在另一個組件的 components 選項中傳入這個組件即可。
import header from './components/header/header.vue';
export default {
data () {
},
components: {
'v-header': header
}
};
構成組件
data對象
data 必須是函數。因為如果不是函數的,聲明多個組件的時候,他們共享的就是同一個data,這樣就會亂掉。如果通過函數返回,那么每個組件維持自己的data作用域。該data屬性只在其component中可見。
通過 prop 傳遞數據
組件實例的作用域是孤立的,組件和組件之間,即使有同名屬性,值也不共享。這意味着不能並且不應該在子組件的模板內直接引用父組件的數據。可以使用 props 把數據傳給子組件。
Vue.component('child', {
// 聲明 props
props: ['message'],
// 就像 data 一樣,prop 可以用在模板內
// 同樣也可以在 vm 實例中像 “this.message” 這樣使用
template: '<span>{{ message }}</span>'
})
需要注意的是HTML 特性是不區分大小寫的。所以,當使用的不是字符串模版,camelCased (駝峰式) 命名的 prop 需要轉換為相對應的 kebab-case (短橫線隔開式) 命名,這點在angularjs的指令中也一樣。
Vue.component('child', {
// camelCase in JavaScript
props: ['myMessage'],
template: '<span>{{ myMessage }}</span>'
})
<!-- kebab-case in HTML --> <child my-message="hello!"></child>
在vue2.0中prop 是單向綁定的:當父組件的屬性變化時,將傳導給子組件,但是不會反過來。這是為了防止子組件無意修改了父組件的狀態——這會讓應用的數據流難以理解。每次父組件更新時,子組件的所有 prop 都會更新為最新值。這意味着你不應該在子組件內部改變 prop 。如果你這么做了,Vue 會在控制台給出警告。這點官方文檔給出了明確的說明和解決辦法。
當我開發一個通用組件時,需要對傳入的數據進行嚴格的驗證,我們可以定義傳入數據的類型,同時也可以設置其默認值。如果傳入的數據不符合規格,Vue 會發出警告。
Vue.component('example', {
props: {
// 基礎類型檢測 (`null` 意思是任何類型都可以)
propA: Number,
// 多種類型
propB: [String, Number],
// 必傳且是字符串
propC: {
type: String,
required: true
},
// 數字,有默認值
propD: {
type: Number,
default: 100
},
// 數組/對象的默認值應當由一個工廠函數返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定義驗證函數
propF: {
validator: function (value) {
return value > 10
}
}
}
})
type 可以是下面原生構造器:
- String
- Number
- Boolean
- Function
- Object
- Array
type 也可以是一個自定義構造器函數,使用 instanceof 檢測。
生命周期
Vue實例有一個完整的生命周期,也就是從開始創建、初始化數據、編譯模板、掛載Dom、渲染→更新→渲染、卸載等一系列過程,我們稱這是Vue的生命周期。通俗說就是Vue實例從創建到銷毀的過程,就是生命周期。首先看看下面官網的一張生命周期的圖:

Vue提供的可以注冊的鈎子都在上圖片的紅色框標注。 他們分別是:
- beforeCreate:在實例初始化之后,數據觀測(data observer) 和 event/watcher 事件配置之前被調用。
- created:實例已經創建完成之后被調用。在這一步,實例已完成以下的配置:數據觀測(data observer),屬性和方法的運算, watch/event 事件回調。然而,掛載階段還沒開始,$el 屬性目前不可見。
- beforeMount:在掛載開始之前被調用:相關的 render 函數首次被調用。
- mounted:el 被新創建的 vm.$el 替換,並掛載到實例上去之后調用該鈎子。如果 root 實例掛載了一個文檔內元素,當 mounted 被調用時 vm.$el 也在文檔內。
- beforeUpdate:數據更新時調用,發生在虛擬 DOM 重新渲染和打補丁之前。 你可以在這個鈎子中進一步地更改狀態,這不會觸發附加的重渲染過程。
- updated:由於數據更改導致的虛擬 DOM 重新渲染和打補丁,在這之后會調用該鈎子。當這個鈎子被調用時,組件 DOM 已經更新,所以你現在可以執行依賴於 DOM 的操作。然而在大多數情況下,你應該避免在此期間更改狀態,因為這可能會導致更新無限循環。該鈎子在服務器端渲染期間不被調用。
- beforeDestroy:實例銷毀之前調用。在這一步,實例仍然完全可用。
- destroyed:Vue 實例銷毀后調用。調用后,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀。 該鈎子在服務器端渲染期間不被調用。
