绑定自定义事件
说到 Vue 自定义事件,那就需要搞清楚一个问题,为啥有这个玩意。
说到自定义事件之前,需要理解 组件基础的概念。理解了基础概念之后,我们就知道 Vue 的父子之间的通信, 一是 父组件通过 Prop 向子组件传递数据 。二是 监听子组件事件。
具体详情参考之前的博文:Vue-父子组件传值。
vue-07-父子组件传值_vue handler(n) {}_白桃味稠鱼烧的博客-CSDN博客因为vue 的数据是单向流动的,这是为了避免数据污染。在官方文档中也说到:所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。大致归纳一下:父传子--传值、子传父--传事件1、父传子如果传递的数据是对象格式的,那么在子组件 内部监..._vue handler(n) {}https://blog.csdn.net/qq_40792800/article/details/105559859这篇博文中详细说明了 父子组件传值的方法,其中就有 子组件传递数据给父组件的三种方法,其实就是 通过自定义事件 来实现的。实现方法也在其中详细说明了。
$off:解绑自定义事件
上面说过了 通过绑定自定义事件,实现了子组件向父组件传递数据,那么既然有绑定方法,就应该和原生js一样,有解绑的方法,也存在解绑的方法,那就是 $off() 。
-
如果没有提供参数,则移除所有的事件监听器;
-
如果只提供了事件,则移除该事件所有的监听器;
-
如果同时提供了事件与回调,则只移除这个回调的监听器
父组件只使用一种绑定方法
<School @test="test"/>
methods: {
test(val) {
console.log(val,'这是子组件传递过来的数据')
},
},
子组件解绑事件
1、只提供事件,则移除该事件所有的监听器( 只传递一个事件和传递多个事件 )
<template>
<div>
<p class="demo" @click="goto">School组件</p>
<p @click="unbind">解绑事件</p>
</div>
</template>
export default {
data() {
return {
msg: "子组件数据",
};
},
methods: {
goto() {
this.$emit("test", this.msg);
},
unbind() {
console.log("解绑事件");
this.$off('test'); // 若只传递一个参数,则只解绑一个自定义事件
this.$off(['test1','tset2','test3']); // 若传递一个数组,则同时解绑传递的多个自定义事件
},
},
};
触发父组件事件之后,点击触发解绑事件,再次触发父组件事件,无法打印出子组件数据
2、同时提供了事件与回调,则只移除这个回调的监听器
- 我在子组件的 mounted 生命周期中 监听了 myEvent 事件,且该事件上存在两个回调函数
- 点击 测试按钮时,$emit 触发 myEvent 事件,myEvent 事件上的回调函数全部触发
- 点击解绑按钮,解绑 myEvent 事件 上的 this.myCallback() 函数,只剩下 匿名函数
- 再次点击 测试按钮,发现 myEvent 事件 上,this.myCallback() 函数不触发,匿名函数触发
<template>
<div>
<p @click="test">测试</p>
<p @click="remove">解绑myCallback</p>
</div>
</template>
<script>
export default {
mounted() {
// 添加事件监听器,在组件挂载后执行 myCallback 函数
this.$on('myEvent', this.myCallback);
this.$on('myEvent', () => {
console.log('我是匿名函数,我被触发了')
});
},
methods: {
test() {
this.$emit('myEvent')
},
remove() {
console.log('我解绑了myCallback,但是没有解绑匿名函数')
this.$off('myEvent',this.myCallback)
},
myCallback() {
console.log('我是myCallback,我被触发了')
}
},
};
</script>
ps:$on 监听事件之后,需要 $emit 触发事件监听,才去执行 $off,不然绑定的事件没触发,看不出来效果( 绑定事件都不触发,你解绑它干啥,直接不监听就行了啵 )
3、 如果没有提供参数,则移除所有的事件监听器
在父组件中给 School子组件 绑定两个自定义事件
<School @test="test" @test1="test1"/>
methods: {
test(val) {
console.log(val,'这是子组件传递过来的数据')
},
test1(val) {
console.log(val,'这是子组件传递过来的数据1')
},
},
在子组件中触发两个绑定的自定义事件
<template>
<div>
<p @click="bind">绑定</p>
<p @click="remove">解绑</p>
</div>
</template>
<script>
export default {
methods: {
bind() {
this.$emit('test','test')
this.$emit('test1','test1')
},
remove() {
this.$off()
},
},
};
</script>
- 点击 bind 触发绑定事件,控制台上会打印出数据。
- 点击 remove 移除所有绑定事件。
- 再次点击 bind 触发绑定事件,控制台无输出,表明所有绑定事件已移除
Vue destroyed() 生命周期
实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
<template>
<div>
<p @click="bind">绑定</p>
<p @click="death">销毁子组件</p>
</div>
</template>
<script>
export default {
methods: {
bind() {
this.$emit('test','test')
this.$emit('test1','test1')
},
death() {
this.$destroy()
}
},
};
</script>
- 点击 bind 按钮,触发绑定函数,控制台上输出。
- 点击 销毁子组件 按钮,销毁子组件,移除所有事件监听器,解绑所有指令
- 再次点击 bind 按钮,控制台无输出
总结
1、组件的自定义事件是一种组件间的通信方式:子组件 向 父组件 传递数据。
2、使用场景:子组件B 向 父组件A 传递数据,需要在 父组件A 中给 子组件B 绑定自定义事件( 事件的回调在 A 中 )
3、绑定自定义事件:
- 第一种方式:在父组件中
-
<School @test="test"/> <School v-on:test="test"/>
- 第二种方式:在父组件中
-
<School ref='student'/> mounted() { this.$refs.student.$on('qwe', this.getname) }
- 第三种方式:若想让自定义事件只能触发一次,可以使用 once 修饰符,或 $ones 方法
4、触发自定义事件
this.$emit('test','向传递的数据')
5、解绑自定义事件
this.$off()
6、也可以使用 生命周期钩子函数 this.$destroy() 来销毁组件达到解绑所有自定义事件
7、组件上也可以绑定 原生DOM事件,使用 .native 事件。即使是 @click 事件,Vue也不会将其解析为 自定义事件,不用在 School 子组件中 使用 $emit 触发
<School @click.native="test"/>
8 、注意:通过 this.$refs.xxx.$on( 'xxx' , callback ),绑定自定义事件时,callback 回调要么配置在 mtenods 中,要么使用箭头函数,否则 this 指向存在问题( 因为 callback 函数接收的参数都是从子组件中传递的,包括 this也是,如果使用 function () {} 函数,则该函数内部 this 指向子组件 )