
上篇:VUE從入門到入坑—04.v-model指令 / 事件綁定指令 / 修飾符 / 深度響應式
一、什么是組件
組件就是零件,將零件組裝成想要的工具(頁面),組件是vue.js最強大的功能之一,它可以擴展html元素,封裝可重用的代碼,通過傳入對象的不同,實現(xiàn)組件的復用。
1.定義全局組件
全局組件:使用Vue.component來創(chuàng)建全局組件,可以用在創(chuàng)建的 Vue 根實例 (new Vue) 的模板中,任何方式,任何地點都可以使用的標簽組件。
Vue.component('mx-box', {
template:`
<div>
<h1>標題</h1>
</div>
`,
props:{ },
data() {
return { }
}
})
new Vue({ el: '#app' })
<div id="app">
<mx-box> </mx-box>
</div>
2.定義局部組件
只能在定義它的el中使用,不能在其他位置,否則就會失效。
new Vue({
el: '#app',
components: {
// 自定義組件名
'mx-box': {
template:`
<div>
<p> hello </p>
</div>
`,
props:{ },
data() {
return { }
}
}
}
})
<div id="app">
<mx-box> </mx-box>
</div>
(1)components選項中定義局部組件。每個組件就是一個小型的Vue實例,它里面除了不能設置el選項,其他選項它都有。
(2)組件名稱:自定義,可以使用駝峰命名方式或者短橫線的命名方式,但是需要注意的是如果應用到DOM中,就只能用短橫線命名的方式,否則就會報錯。注意組件的名稱不要跟原生html元素重名。
(3)template選項:定義組件的模板。模板中必須包含一個根標簽。
(4)props選項:定義組件標簽上的屬性。駝峰命名法的 prop 名(postTitle)需要使用其等價的短橫線分隔命名法(post-title)命名。注意:props是只讀的,不能修改(解決辦法:在data中對props接收到的數(shù)據(jù)進行中轉)。
(5)props的值可以是一個字符串數(shù)組,里面定義每一個標簽屬性名稱,這是簡單用法,不能對屬性做嚴格的驗證。例如:props:["count"]。
(6)props的值可以是一個對象,里面定義每個標簽屬性名稱,以及對應的類型。例如:props:{ count:Number }。
(7)props的值可以是一個對象,里面定義的每個標簽屬性名稱也可以是一個對象,在這個對象里面定義該屬性的完整信息。type 定義類型,required 非空,default 默認值。例如:props: {count: { type: Number, required: true, default: 1 } }
(8)data:定義組件的數(shù)據(jù)。注意:Vue實例的data選項可以是一個對象,也可以是一個方法,由該方法返回一個對象。 但是在組件中,data選項必須是一個方法,由該方法返回一個對象。因為組件可能會使用很多次,如果data選項是對象的話,會導致多個組件使用了同一份數(shù)據(jù)。
二、全局組件和局部組件的區(qū)別
全局:可以再頁面中任何位置使用。
局部:只能在定義它的el中使用,不能在其他位置,否則就會失效。
定義方法
全局:可以使用Vue.component(tagName,options)定義。
局部:可以通過Vue實例中component屬性定義局部組件。
是否掛載:全局組件在擴展元素用于封裝復用代碼時不需要掛載,但是不常見,因為會影響瀏覽器的性能 局部組件必須手動掛載,否則會失效。
其他 局部組件中代碼的編寫是”components“,而全局組件中是”component“ 。
三、$emit()自定義事件
Vue為每個組件對象提供了一個內(nèi)置方法:$emit,作用:子組件向父組件傳值,觸發(fā)自定義事件,注意:事件名稱中不能采用大寫字母。
// 觸發(fā)一個自定義事件,事件名稱是synccount,將val作為事件對象傳出去
this.$emit('synccount',val)
<mx-box @synccount="synccount(doSomething)"> </mx-box>
四、練習,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
}
},
// 注冊組件
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選項
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,中轉給myCount
myCount: this.count
}
},
// 監(jiān)聽器
watch: {
// 偵聽myCount是否發(fā)生變化
myCount(val) {
// 觸發(fā)一個自定義事件synccount,將count的最新值作為事件對象傳出去
this.$emit('synccount', val)
}
}
}
}
})
效果:

五、練習,評分組件
<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>
// 注冊全局組件
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>
`,
// 定義組件的標簽屬性
props:{
title:{
type:String,
required:false
},
value:{
type:Number,
default:0
}
},
// 數(shù)據(jù)
data() {
return {
// 中轉props傳進來的value值
myValue:this.value,
// 定義一個確定值
okValue:this.value
}
},
// 方法
methods: {
// 鼠標進入時,調(diào)用的方法
enter(val){
this.myValue = val
},
// 鼠標離開時,調(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)品質量',
value:5
},
{
title:'物流速度',
value:7
},
{
title:'客服態(tài)度',
value:2
}
]
},
methods: {
// 同步評分
syncvalue(index,e){
this.list[index].value = e
}
},
})
效果:
