依然利用沿用上次的例子(去掉了component組件中的點擊事件,出現(xiàn)"clicked"彈窗的方法):
<body>
<div id="root">
<div>
<input v-model="inputValue" />
<button @click="handleSubmit">提交</button>
</div>
<ul>
<todo-item
v-for="(item, index) of list"
:key="index"
:content="item"
>
</todo-item>
</ul>
</div>
<script>
Vue.component('todo-item',{
props:['content'],
template:'<li @click="handleClick">{{content}}</li>',
})
new Vue({
el:"#root",
data:{
inputValue:'hello',
list:[]
},
methods:{
handleSubmit:function(){
this.list.push(this.inputValue)
this.inputValue =''
}
}
})
</script>
</body>
現(xiàn)在要實現(xiàn)一個需求:點擊li標簽的數(shù)據(jù),數(shù)據(jù)可以被刪除。
分析一下這個需求:li標簽是在子組件中創(chuàng)建的,但是li標簽內(nèi)的數(shù)據(jù)是來自父組件,如果要刪除子組件的這個數(shù)據(jù),肯定要刪除父組件中對應(yīng)的數(shù)據(jù)。
在Vue中,實現(xiàn)子組件和父組件之間的通訊,需要一個發(fā)布訂閱模式來處理。
在處理這個需求之前,還需要一個參數(shù),是當前子組件在list中的下標。在ul中,父組件循環(huán)顯示子組件的時候,額外再帶一個參數(shù)index,這個參數(shù)等于循環(huán)顯示的下標index(即“:index='index'”),然后再component組件中的props內(nèi)增加這個index(即:“props:['content','index']”),讓子組件接收父組件中的content屬性的同時,接收index屬性,
嘗試下能不能接收到index屬性,component中的template模板增加一個插值表達式{{index}},template的模板即寫成:
template:'<li @click="handleClick">{{content}}{{index}}</li>',
結(jié)果是:

可以看到子組件成功接收了list下標?,F(xiàn)在刪除template中的{{index}}。
在需求中,可以看到是點擊li標簽,然后會刪除li標簽的內(nèi)容。
這樣其實是在點擊li標簽的時候,觸發(fā)了是一個事件,這個事件將刪除li標簽的內(nèi)容。
但是li標簽是在子組件中創(chuàng)建的,list的內(nèi)容是是在父組件中創(chuàng)建的,如何將刪除li標簽的刪除傳達到父組件中,將是這節(jié)的重點。
點擊li標簽將觸發(fā)事件,這個事件的方法刪除父組件中的數(shù)據(jù)。直接刪除是不可能的,因為無法通信。
答案是通過訂閱模式,子組件創(chuàng)建一個自定義的事件,在模板中綁定delete事件和一個新的方法(handleDelete,方法將刪除數(shù)據(jù)),當觸發(fā)這個方法的時候,模板中會監(jiān)聽到這個事件的觸發(fā),然后handleDelete事件將起作用,然后刪除數(shù)據(jù)。
下面是代碼的具體表現(xiàn):
<body>
<div id="root">
<div>
<input v-model="inputValue" />
<button @click="handleSubmit">提交</button>
</div>
<ul>
<todo-item
v-for="(item, index) of list"
:key="index"
:content="item"
:index="index"
@delete="handleDelete"
>
</todo-item>
</ul>
</div>
<script>
Vue.component('todo-item',{
props:['content','index'],
template:'<li @click="handleClick">{{content}}</li>',
methods:{
handleClick:function(){
this.$emit('delete',this.index)
}
}
})
new Vue({
el:"#root",
data:{
inputValue:'hello',
list:[]
},
methods:{
handleSubmit:function(){
this.list.push(this.inputValue)
this.inputValue =''
},
handleDelete: function(index) {
this.list.splice(index, 1)
}
}
})
</script>
</body>
當點擊li標簽的時候,會觸發(fā)handleClick方法,這個方法向外釋放了一個名為delete的事件,這個事件對應(yīng)的值是觸發(fā)的內(nèi)容的下標簽。
因為在父標簽中訂閱了delete事件(@delete="handleDelete"),當觸發(fā)的時候,就會執(zhí)行handleDelete方法(handleDelete方法是父組件還是子組件的?是父組件的,因為它寫在父組件對應(yīng)的模板中),這個方法將刪除所點擊的內(nèi)容(function括號內(nèi)的index參數(shù)是接收的參數(shù),將指導(dǎo)下標對應(yīng)的什么數(shù)據(jù)內(nèi)容)