前言:這一篇是關於組件基礎、組件注冊、Prop等內容。
1.組件基礎
01.組件是可復用的Vue實例
02.組件中的data選項必須是一個函數
03.一個組件默認可以有任意數量的prop
任何值都可以傳遞給任何prop。就像訪問data一樣。
04.使用$emit監聽子組件事件
一個全局的子組件代碼:
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button v-on:click="$emit('enlarge-text', 0.1)">放大文字</button>
<div v-html="post.content"></div>
</div>
`
})
父組件代碼:
<blog-post v-bind:post="post" :style="{fontSize: postFontSize + 'em'}" v-on:enlarge-text="onEnlargeText"></blog-post>
var vm = new Vue({ el: '#app', data: { post: { id: 1, title: '給一個青年詩人的十封信', content: '<p>Vue從入門到實戰</p>' }, postFontSize: 1 }, methods: { onEnlargeText: function (enlargeAmount) { this.postFontSize += enlargeAmount } } })
05.使用事件拋出一個值
子組件的一個事件可以通過$emit的第二個參數來提供一個值,在父級組件監聽這個事件時,通過$event訪問被拋出的這個值。
<blog-post ... v-on:enlarge-text="postFontSize += $event" ></blog-post>
06.在組件上使用v-model
自定義事件也可以用於創建支持v-model的自定義輸入組件
<input v-model="searchText">
等價於:
<input v-bind:value="searchText" v-on:input="searchText = $event.target.value" >
當用在組件上時,v-model則會這樣:
<custom-input v-bind:value="searchText" v-on:input="searchText = $event" ></custom-input>
為了讓它正常工作,這個組件內的<input>必須:
- 將其value特性綁定到一個名叫value的prop上
- 在其input事件被觸發時,將新的值通過自定義的input事件拋出
示例如下:
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
現在v-model就應該可以在這個組件上完美地工作起來了:
<custom-input v-model="searchText"></custom-input>
07.動態組件
Vue有一個<component>元素,它有一個is屬性
<!-- 組件會在 `currentTabComponent` 改變時改變 --> <component v-bind:is="currentTabComponent"></component>
在上述示例中,currentTabComponent可以包括:
- 已注冊組件的名字,或
- 一個組件的選項對象
08.特殊的is屬性的妙用
有些html元素,諸如<ul>、<ol>、<table>、<select>,對於哪些元素可以出現在其內部是有嚴格限制的。
<table> <blog-post-row></blog-post-row> </table>
這個自定義組件<blog-post-row>會被作為無效的內容提升到外部,使用is特性可解決:
<table> <tr is="blog-post-row"></tr> </table>
2.Prop
01.Prop類型
props: { title: String, likes: Number, isPublished: Boolean, commentIds: Array, author: Object, callback: Function, contactsPromise: Promise // or any other constructor }
02.傳入一個對象的所有屬性
如果你想要將一個對象的所有屬性都作為prop傳入,你可以使用不帶參數的v-bind取代b-bind:prop-name,例如:
post: { id: 1, title: 'My Journey with Vue' }
下面的模板:
<blog-post v-bind="post"></blog-post>
等價於:
<blog-post v-bind:id="post.id" v-bind:title="post.title" ></blog-post>
03.單向數據流
所有的prop都使得其父子prop之間形成了一個單向下行綁定
每次父級組件發生更新時,子組件中所有的prop都將會刷新為最新的值。這意味着你不應該在一個子組件內部改變prop。
04.Prop驗證
這在開發一個會被別人用到的組件時尤其有幫助。
Vue.component('my-component', {
props: {
//基礎的類型檢查
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 ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
注意:那些prop會在一個組件實例創建之前進行驗證,所以實例的屬性(如data、computed等)在default或validator函數中不可用。
05.類型檢查
type可以時下列原生構造函數中的一個:
- String
- Number
- Boolean
- Array
- Object
- Date
- Function
- Symbol
type還可以是一個自定義的構造函數,並且通過instanceof來進行檢查確認。例如,給定下列現成的構造函數:
function Person (firstName, lastName) { this.firstName = firstName this.lastName = lastName }
你可以使用:
Vue.component('blog-post', {
props: {
author: Person
}
})
來驗證author prop的值是否是通過new Person創建的
06.非Prop的特性
(1)組件可以接受任意的特性,而這些特性會被添加到這個組件的根元素上
(2)替換/合並已有的特性
對絕大多數特性來說,從外部提供給組件的值會替換掉組件內部設置好的值。所以如果傳入 type="text" 就會替換掉 type="date" 並把它破壞。 class 和 style會合並兩邊的值。
(3)禁用特性繼承
如果你不希望組件的根元素繼承特性,你可以在組件的選項中設置 inheritAttrs: false
Vue.component('my-component', {
inheritAttrs: false,
// ...
})
一個基礎組件的例子:
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
`
})
注意:inheritAttrs: false不會影響style和class的綁定
這個模式允許你在使用基礎組件的時候更像是使用原始的HTML元素,而不會擔心哪個元素是真正的根元素
<base-input v-model="username" required placeholder="Enter your username" ></base-input>
筆記摘自Vue官方文檔:
