四、实现todolist的删除功能(知识点:子组件向父组件传值)
依然利用沿用上次的例子(去掉了component组件中的点击事件,出现"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>
现在要实现一个需求:点击li标签的数据,数据可以被删除。
分析一下这个需求:li标签是在子组件中创建的,但是li标签内的数据是来自父组件,如果要删除子组件的这个数据,肯定要删除父组件中对应的数据。
在Vue中,实现子组件和父组件之间的通讯,需要一个发布订阅模式来处理。
在处理这个需求之前,还需要一个参数,是当前子组件在list中的下标。在ul中,父组件循环显示子组件的时候,额外再带一个参数index,这个参数等于循环显示的下标index(即“:index='index'”),然后再component组件中的props内增加这个index(即:“props:['content','index']”),让子组件接收父组件中的content属性的同时,接收index属性,
尝试下能不能接收到index属性,component中的template模板增加一个插值表达式{{index}},template的模板即写成:
template:'<li @click="handleClick">{{content}}{{index}}</li>',
结果是:
图片.png
可以看到子组件成功接收了list下标。现在删除template中的{{index}}。
在需求中,可以看到是点击li标签,然后会删除li标签的内容。
这样其实是在点击li标签的时候,触发了是一个事件,这个事件将删除li标签的内容。
但是li标签是在子组件中创建的,list的内容是是在父组件中创建的,如何将删除li标签的删除传达到父组件中,将是这节的重点。
点击li标签将触发事件,这个事件的方法删除父组件中的数据。直接删除是不可能的,因为无法通信。
答案是通过订阅模式,子组件创建一个自定义的事件,在模板中绑定delete事件和一个新的方法(handleDelete,方法将删除数据),当触发这个方法的时候,模板中会监听到这个事件的触发,然后handleDelete事件将起作用,然后删除数据。
下面是代码的具体表现:
<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标签的时候,会触发handleClick方法,这个方法向外释放了一个名为delete的事件,这个事件对应的值是触发的内容的下标签。
因为在父标签中订阅了delete事件(@delete="handleDelete"),当触发的时候,就会执行handleDelete方法(handleDelete方法是父组件还是子组件的?是父组件的,因为它写在父组件对应的模板中),这个方法将删除所点击的内容(function括号内的index参数是接收的参数,将指导下标对应的什么数据内容)