【Vue】自定义事件详解 | this.$emit的使用 | 其中参数传递的逻辑说明
文章目录自定义事件1、 使用背景13.2 示例自定义事件1、 使用背景接着上一章讲的slot插槽的页面。<body><div id="app"><todo><todo-title slot="todo-title" :tit="title"></todo-title><todo-items slot="todo-items" :it
自定义事件
1、 使用背景
接着上一章讲的slot插槽的页面。
<body>
<div id="app">
<todo>
<todo-title slot="todo-title" :tit="title"></todo-title>
<todo-items slot="todo-items" :itm="i" v-for="i in todoItems"></todo-items>
</todo>
</div>
<script>
Vue.component('todo', {
template: '<div>\
<slot name="todo-title"></slot>\
<ul>\
<slot name="todo-items"></slot>\
</ul>\
</div>'
});
Vue.component('todo-title',{
props: ['tit'],
template: '<div>{{tit}}</div>'
});
Vue.component('todo-items',{
props: ['itm'],
template: '<li>{{itm}} <button>删除</button></li>'
});
var vm = new Vue({
el: "#app",
data: {
title: "学习列表",
todoItems: ['Java','前端','Linux']
}
});
</script>
</body>
我在每个item后面都添加一个button按钮,我想让每一行后面点击删除后就删除此行。
组件和组件之间可以用插槽。但是组件想要调用Vue实例里面的方法,还得把data中的某个数据删除?
实际上,组件自身可以写methods方法。
<script>
Vue.component('todo-items',{
props: ['itm'],
template: '<li>{{itm}} <button @click="remove">删除</button></li>',
methods: {
remove: function (){
alert("111")
}
}
});
</script>
说明这个事件绑定成功了。
关键是,我组件里的一个按钮,想要去删Vue实例的data中的某个数组中的某个数据,能删的到吗?
我们试试组件中的按钮能不能调用Vue实例中的methods
<script>
Vue.component('todo-items',{
props: ['itm'],
template: '<li>{{itm}} <button @click="removeItem">删除</button></li>'
});
var vm = new Vue({
el: "#app",
data: {
title: "学习列表",
todoItems: ['Java','前端','Linux']
},
methods: {
removeItem: function (){
alert("123")
}
}
});
</script>
经过测试,发现是无法调用的。是拿不到方法的。
但是不管你用哪里的方法,你总归是要操作Vue实例中data里面的todoItems那个数组中的数据的,这是毫无疑问的。
那我们来看看怎么样可以触发这件事情。
先不管谁来调用,怎么调用;先看看怎么来写一个方法能够删除数组中的元素。
<script>
var vm = new Vue({
el: "#app",
data: {
title: "学习列表",
todoItems: ['Java','前端','Linux']
},
methods: {
removeItem: function (index){
console.log("删除了"+this.todoItems[index]+"OK");
this.todoItems.splice(index,1); //一次删除一个元素
}
}
});
</script>
这里用到了一个js对数组元素进行操作的splice()方法。
我们先直接在控制台执行这个方法,看看能否删除
这个方法本身逻辑是ok的。
那么接下来的问题就是,怎么样用组件中的事件去做这样一个方法呢?
首先,如果真的在某处调用了这一方法,那么先不管是在哪里调用的,肯定要传递一个index参数值。不要忘了v-for是可以遍历出index的。
<div id="app">
<todo>
<todo-title slot="todo-title" :tit="title"></todo-title>
<todo-items slot="todo-items" v-for="(i,index) in todoItems" :itm="i" :indx="index"></todo-items>
</todo>
</div>
<script>
Vue.component('todo-items',{
props: ['itm','indx'],
template: '<li>{{indx}}----{{itm}} <button @click="">删除</button></li>'
});
</script>
可以发现index是取到了的
我们组件中的button按钮的@click事件绑定的方法,永远都只能是组件内定义的methods方法。但是我们要想方设法的向Vue实例中methods定义的removeItems上靠拢。
<script>
Vue.component('todo-items',{
props: ['itm','indx'],
template: '<li>{{indx}}----{{itm}} <button @click="remove">删除</button></li>',
methods: {
remove: function (){
}
}
});
var vm = new Vue({
el: "#app",
data: {
title: "学习列表",
todoItems: ['Java','前端','Linux']
},
methods: {
removeItem: function (index){
console.log("删除了"+this.todoItems[index]+"OK");
this.todoItems.splice(index,1); //一次删除一个元素
}
}
});
</script>
2、 示例
这个问题通过Vue给我们提供的自定义事件
就可以完成了。
通过以上代码不难发现,数据项在Vue的实例中,但是删除操作要在组件中完成,那么组件如何才能删除Vue实例中的数据呢?此时就涉及到参数传递与事件分发了,Vue为我们提供了自定义事件的功能,很好的帮我们解决了这个问题。使用this.$emit(‘自定义事件名’,参数)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
</head>
<body>
<div id="app">
<todo>
<todo-title slot="todo-title" :tit="title"></todo-title>
<todo-items slot="todo-items" v-for="(i,index) in todoItems"
:itm="i" v-on:rem="removeItem(index)"></todo-items>
</todo>
</div>
<script>
Vue.component('todo-items',{
props: ['itm'],
template: '<li>{{itm}} <button @click="remove">删除</button></li>',
methods: {
remove: function (){
this.$emit('rem')
}
}
});
var vm = new Vue({
el: "#app",
data: {
title: "学习列表",
todoItems: ['Java','前端','Linux']
},
methods: {
removeItem: function (index){
alert(index);
this.todoItems.splice(index,1); //一次删除一个元素
}
}
});
</script>
</body>
</html>
捋一遍思路:
- 首先,由于Vue实例是和#app绑定的。所以,处于#app中的自定义标签(组件),是完全可以通过v-on去绑定Vue实例中的事件的。于是有了v-on:rem=“removeItem”
- 自定义标签与Vue实例绑定好了,然后这个组件标签想要与Vue.component中的事件建立绑定,如何完成。就使用到了this.$emit。
- 在组件的methods中定义一个remove方法,这个方法中,通过this.$emit(‘rem’),最终实现了将组件中的remove方法,通过中间属性rem,与Vue实例中的removeItem真正的绑定了起来。在组件中调用remove就相当于调用Vue实例中的removeItem。
- 下标index的传递逻辑为:首先v-for能够遍历出index(这个是v-for的一个默认的功能,index这个变量就是返回索引值的),然后在v-on绑定事件时,将事件的传参设为index。这样,事件的function就会传入真正的那个index下标。
注意:index下标只有在v-for遍历的时候才能取到,它才是真正的遍历数组中的那个数组元素下标,你在其他地方写index都是取不到的,而仅仅是当做一个普通为定义的变量去识别而已,还会告诉你undefined。
如果由于index传值问题导致最终传入this.todoItems.splice(index,1)这个方法中的index部分为“undefined”的话,你会发现数组元素也会一个一个地变少,只不过每次删除都只会移除数组中的第一个元素。
更多推荐
所有评论(0)