一揩懒、注冊(cè)自定義組件
1、局部注冊(cè)
局部注冊(cè)的組件挽封,只能在當(dāng)前Vue實(shí)例中使用已球,并且在其子組件中不可用。
在components選項(xiàng)中定義局部組件。每個(gè)組件就是一個(gè)小型的Vue實(shí)例智亮,它里面除了不能設(shè)置el選項(xiàng)忆某,其他選項(xiàng)它都有。
組件名稱:自定義阔蛉,可以使用駝峰命名方式或者短橫線的命名方式弃舒,但是需要注意的是如果應(yīng)用到DOM中,就只能用短橫線命名的方式状原,否則就會(huì)報(bào)錯(cuò)聋呢。注意組件的名稱不要跟原生html元素重名。
template選項(xiàng):定義組件的模板颠区。模板中必須包含一個(gè)根標(biāo)簽削锰。
props選項(xiàng):定義組件標(biāo)簽上的屬性。駝峰命名法的 prop 名(postTitle)需要使用其等價(jià)的短橫線分隔命名法(post-title)命名毕莱。注意:props是只讀的器贩,不能修改(解決辦法:在data中對(duì)props接收到的數(shù)據(jù)進(jìn)行中轉(zhuǎn))。
- props的值可以是一個(gè)字符串?dāng)?shù)組央串,里面定義每一個(gè)標(biāo)簽屬性名稱磨澡,這是簡單用法,不能對(duì)屬性做嚴(yán)格的驗(yàn)證质和。例如:props:["count"]稳摄。
- props的值可以是一個(gè)對(duì)象,里面定義每個(gè)標(biāo)簽屬性名稱饲宿,以及對(duì)應(yīng)的類型厦酬。例如:props:{ count:Number }。
- props的值可以是一個(gè)對(duì)象瘫想,里面定義的每個(gè)標(biāo)簽屬性名稱也可以是一個(gè)對(duì)象仗阅,在這個(gè)對(duì)象里面定義該屬性的完整信息。type 定義類型国夜,required 非空减噪,default 默認(rèn)值。例如:props: {count: { type: Number, required: true, default: 1 } }
data:定義組件的數(shù)據(jù)。注意:Vue實(shí)例的data選項(xiàng)可以是一個(gè)對(duì)象,也可以是一個(gè)方法边琉,由該方法返回一個(gè)對(duì)象和媳。 但是在組件中赶诊,data選項(xiàng)必須是一個(gè)方法,由該方法返回一個(gè)對(duì)象。因?yàn)榻M件可能會(huì)使用很多次,如果data選項(xiàng)是對(duì)象的話抗斤,會(huì)導(dǎo)致多個(gè)組件使用了同一份數(shù)據(jù)囚企。
new Vue({
el: '#app',
components: {
// 自定義組件名
'component-name': {
template:`
<div>
<p> hello </p>
</div>
`,
props:{ },
data() {
return { }
}
}
}
})
<div id="app">
<component-name> </component-name>
</div>
2、全局注冊(cè)
全局注冊(cè)的組件可以用在任何新創(chuàng)建的 Vue 根實(shí)例 (new Vue) 的模板中瑞眼。
使用Vue.component來創(chuàng)建全局組件龙宏。Vue.component的第一個(gè)參數(shù)就是組件名。
Vue.component('component-name', {
template:`
<div>
<p> hello </p>
</div>
`,
props:{ },
data() {
return { }
}
})
new Vue({ el: '#app' })
<div id="app">
<component-name> </component-name>
</div>
二伤疙、自定義事件 $emit()
$emit()用于觸發(fā)自定義事件烦衣。注意:事件名稱中不能采用大寫字母。
// 觸發(fā)一個(gè)自定義事件掩浙,事件名稱是synccount,將val作為事件對(duì)象傳出去
this.$emit('synccount',val)
<component-name @synccount="synccount(doSomething)"> </component-name>
三秸歧、counter組件
<div id="app">
<ul class="list">
<li v-for="(item,index) in list" :key="index">{{item.label}}--{{item.count}}</li>
</ul>
<b-counter v-for="(item,index) in list" :key="index" :label="item.label" :count="item.count"
@synccount="synccount(index,$event)"></b-counter>
</div>
new Vue({
el: '#app',
// 定義數(shù)據(jù)
data: {
list: [
{ label: '衣服',count: 5 },
{ label: '褲子',count: 8 },
{ label: '鞋子',count: 3 },
{ label: '襪子',count: 10 }
]
},
methods: {
synccount(index, e) {
// 同步更新商品的數(shù)量
this.list[index].count = e
}
},
// 注冊(cè)組件
components: {
'b-counter': {
template: `
<div class="counter">
<div class="label">{{label}}</div>
<div class="btns">
<button @click="myCount--" :disabled="myCount===minCount">-</button>
<input readonly class="text" type="text" :value="myCount">
<button @click="myCount++" :disabled="myCount===maxCount">+</button>
</div>
</div>
`,
//props選項(xiàng)
props: {
// 文本
label: {
type: String,
// 允許為空
required: false,
},
// 數(shù)量
count: {
type: Number,
// 非空
required: true
},
// 最大值
maxCount: {
type: Number,
default: 999
},
// 最小值
minCount: {
type: Number,
default: 1
}
},
//定義數(shù)據(jù)
data() {
return {
// 將props接收到的count厨姚,中轉(zhuǎn)給myCount
myCount: this.count
}
},
// 監(jiān)聽器
watch: {
// 偵聽myCount是否發(fā)生變化
myCount(val) {
// 觸發(fā)一個(gè)自定義事件synccount,將count的最新值作為事件對(duì)象傳出去
this.$emit('synccount', val)
}
}
}
}
})
效果:
四键菱、評(píng)分組件
<div id="app">
<ul class="list">
<li v-for="(item,index) in list" :key="index">{{item.title}}--{{item.value}}</li>
</ul>
<b-star v-for="(item,index) in list" :key="index"
:title="item.title" :value="item.value" @syncvalue="syncvalue(index,$event)"></b-star>
</div>
// 注冊(cè)全局組件
Vue.component('b-star', {
//模板
template:`
<div class="star">
<div class="title">{{title}}</div>
<div>
<i v-for="item in 10" :key="item" class="iconfont"
:class="item<=myValue?'icon-xingxing':'icon-star'"
@mouseenter="enter(item)" @mouseleave="leave(item)" @click="okValue=item"></i>
</div>
</div>
`,
// 定義組件的標(biāo)簽屬性
props:{
title:{
type:String,
required:false
},
value:{
type:Number,
default:0
}
},
// 數(shù)據(jù)
data() {
return {
// 中轉(zhuǎn)props傳進(jìn)來的value值
myValue:this.value,
// 定義一個(gè)確定值
okValue:this.value
}
},
// 方法
methods: {
// 鼠標(biāo)進(jìn)入時(shí)谬墙,調(diào)用的方法
enter(val){
this.myValue = val
},
// 鼠標(biāo)離開時(shí),調(diào)用的方法
leave(val){
this.myValue = this.okValue
}
},
// 監(jiān)聽器
watch:{
// 偵聽okValue的變化
okValue(val){
// 觸發(fā)自定義事件
this.$emit('syncvalue',val)
}
}
})
new Vue({
el:'#app',
data:{
list:[
{
title:'產(chǎn)品質(zhì)量',
value:5
},
{
title:'物流速度',
value:7
},
{
title:'客服態(tài)度',
value:2
}
]
},
methods: {
// 同步評(píng)分
syncvalue(index,e){
this.list[index].value = e
}
},
})
效果:
五经备、組件中的插槽
slot 用于在組件的內(nèi)部定義插槽拭抬,組件標(biāo)簽之間的所有html內(nèi)容,會(huì)在插槽所在位置呈現(xiàn)侵蒙。
<div id="app">
<b-tab :list="list" :active="activeIndex">
<h2>全國著名小吃</h2>
</b-tab>
</div>
Vue.component('b-tab', {
template: `
<div class="tab">
<slot></slot>
<ul class="titles">
<li @click="activeIndex=index" :class="{active:activeIndex===index}" v-for="(item,index) in list" :key="index">{{item.title}}</li>
</ul>
<ul class="contents">
<li v-show="activeIndex===index" v-for="(item,index) in list" :key="index">{{item.content}}</li>
</ul>
</div>
`,
props: ['list', 'active'],
data() {
return {
activeIndex: this.active
}
}
})
new Vue({
el: '#app',
data: {
// 高亮索引
activeIndex: 0,
list: [
{
title: '北京',
content: '北京的糖葫蘆真好吃'
},
{
title: '南京',
content: '南京的鹽水鴨真好吃'
},
{
title: '武漢',
content: '武漢的熱干面真好吃'
},
{
title: '長沙',
content: '長沙的臭豆腐真好吃'
}
]
}
})
效果: