Vue-101-Day 12
07 Jun 2019 |Vue提供Component
讓Vue Instance可以重複使用這些Component
。
Component範例:
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: `<button v-on:click="count++">You clicked me {{ count }} times.</button>`
})
var vm14 = new Vue({
el: '#app-14'
})
定義完Component後,再View中使用Component定義名稱 button-counter
<div id="app-14">
<button-counter></button-counter>
</div>
重複使用Component
即定義所要的Component名稱及數量即可
<div id="app-14">
<button-counter></button-counter>
<button-counter></button-counter>
</div>
註:Component所使用的data屬性必須是Function,而不是Object
使用Props屬性傳遞資料給Component
可以註冊attribute在Component的Props裡面,一個Component裡面可以有多個props
。
範例:
Vue.component('blog-post', {
props: ['title', 'author'],
template: `<h3>{{ title }}, author is {{ author }}</h3>`
})
var vm15 = new Vue({
el: '#app-15'
})
輸出結果
My first Vue, author is David
NBA Finals, author is Silver
可以透過資料數量來決定元件重複的數量
範例:此處的posts長度為3,所以需要重複三次post這個元件
Vue.component('post', {
props: ['title'],
template: `<h3>{{ title }}</h3>`
})
var vm16 = new Vue({
el: '#app-16',
data: {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
]
}
})
<div id="app-16">
<post
v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"
></post>
</div>
輸出結果
My journey with Vue
Blogging with Vue
Why Vue is so fun
通常一個元件裡面應該會顯示多個訊息,以上述來說,通常除了顯示title外,還會顯示content。
所以我們將元件調整如下
Vue.component('writings', {
props: ['title', 'content'],
template: `<h3>{{ title }}</h3> <h4>{{content}}</h4>`
})
乍似沒問題,但打開console會看到錯誤訊息如下
[Vue warn]: Error compiling template:
Component template should contain exactly one root element. ....
簡單來說只能有一個根元素
,上述範例同時有兩個根元素 h3 及 h4,所以會出現問題
應該調整為
Vue.component('writings', {
props: ['title', 'content'],
template: `
<div>
<h3>{{ title }}</h3>
<h4>{{ content }}</h4>
</div>
`
})
var vm17 = new Vue({
el: '#app-17',
data: {
posts: [
{ id: 2, title: 'Blogging with Vue', content: 'Hellooooooo' },
{ id: 3, title: 'Why Vue is so fun', content: 'Hiiiiiii' }
]
}
})
隨著要顯示的資料越來越多,程式就必須做重構
只留下post這個attribute,顯示內容皆透過post取得
Vue.component('writings', {
props: ['post'],
template: `
<div>
<h3>{{ post.title }}</h3>
<h4>{{ post.content }}</h4>
<h5>{{ post.author }}</h5>
</div>
`
})
var vm17 = new Vue({
el: '#app-17',
data: {
posts: [
{
id: 2,
title: 'Blogging with Vue',
content: 'Hellooooooo',
author: 'David'
},
{ id: 3, title: 'Why Vue is so fun', content: 'Hiiiiiii', author: 'Mike' }
]
}
})
<div id="app-17">
<writings
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
></writings>
</div>
監聽Component事件
有時候需要與使用者互動,因此必須監聽該Component。
實作一個範例,使用者點擊按鈕,文字會隨著加大
Vue.component('writings', {
props: ['post'],
template: `
<div>
<h3>{{ post.title }}</h3>
<button>
Enlarge Text
</button>
<div v-html="post.content"></div>
</div>
`
})
var vm18 = new Vue({
el: '#app-18',
data: {
posts: [
{
id: 1,
title: 'Blogging with Vue'
},
{ id: 2, title: 'Why Vue is so fun' }
],
pageFontSize: 1
}
})
這時候點擊按鈕並沒有觸發任何事件,所以要開始實作這個功能
先再Button註冊Click事件,點擊時觸發自定義的事件並利用$emit
觸發事件
Vue.component('writings', {
props: ['post'],
template: `
<div>
<h3>{{ post.title }}</h3>
<button v-on:click="$emit('enlargetext')">
Enlarge text
</button>
<div v-html="post.content"></div>
</div>
`
})
利用v-on接收自定義(enlargetext)的事件
<div id="app-18">
<div :style="{fontSize: pageFontSize + 'em'}">
<writings
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
v-on:enlargetext="pageFontSize += 0.1"
></writings>
</div>
</div>
註:HTML attribute是沒有區分大小寫
伴隨事件發射一個值
可以再事件emit時,給定額外的value值
Vue.component('writings', {
props: ['post'],
template: `
<div>
<h3>{{ post.title }}</h3>
<button v-on:click="$emit('enlargetext', 0.1)">
Enlarge text
</button>
<div v-html="post.content"></div>
</div>
`
})
透過$event
,接收被拋出的值(上述為0.1)
<div id="app-18">
<div :style="{fontSize: pageFontSize + 'em'}">
<writings
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
v-on:enlargetext="pageFontSize += $event"
></writings>
</div>
</div>
或是將處理事件當作method處理
var vm18 = new Vue({
el: '#app-18',
data: {
posts: [
{
id: 1,
title: 'Blogging with Vue',
content: 'Helloooooo'
},
{ id: 2, title: 'Why Vue is so fun', content: 'Hiiiiiiii' }
],
pageFontSize: 1
},
methods: {
onEnlargeText: function (enlargeAmount) {
this.pageFontSize += enlargeAmount
}
}
})
<div id="app-18">
<div :style="{fontSize: pageFontSize + 'em'}">
<writings
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
v-on:enlargetext="onEnlargeText"
></writings>
</div>
</div>
在Component使用v-model
下述兩個HTML是相等的
<input v-model="searchText" />
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
/>
用於Component上會是
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
/>
`
})
var vm19 = new Vue({
el: '#app-19',
data: {
searchText: ''
}
})
<div id="app-19">
<custom-input v-model="searchText"></custom-input>
</div>
參考資料:
Comments