2.4 触发自定义事件向处理函数传递多个参数
在接收参数时,不想书写多个形参,可以使用
...
扩展运算符将多个参数进行接收。
App.vue
<template> <div class="app"> <h1>{{msg}}</h1> <School :getSchoolName="getSchoolName"></School> <!-- 1. 为子组件绑定自定义事件 MyEvent 当自定义事件 MyEvent 被触发时, 会调用事件的处理函数 getStudentName --> <!-- <Student @MyEvent="getStudentName"></Student> --> <!-- 2. 使用 ref 进行自定义事件的绑定 --> <Student ref="student"></Student> </div> </template> <script> //导入子组件 import Student from './components/Student' import School from './components/School' export default { name: 'App', components: { School, Student }, data() { return { msg: '你好啊!' } }, methods: { getSchoolName(name) { console.log('App收到了学校名:', name) }, getStudentName(name, ...params) { console.log('App收到了学生名:', name) console.log('其他参数:', params) } }, mounted() { // 为子组件 Student 绑定自定义事件 this.$refs.student.$on('MyEvent', this.getStudentName) } } </script> <style scoped> .app { background-color: gray; padding: 5px; } </style>
Student.vue
<template> <div class="student"> <h2>学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> <button @click="sendStudentName">把学生姓名给App</button> </div> </template> <script> export default { name:'Student', data() { return { name:'张三', sex:'男' } }, methods: { sendStudentName() { console.log('点击了按钮"把学生姓名给App"') // 触发自定义事件 // 将学生姓名传递给自定义事件的处理函数 // 传递多个参数 this.$emit('MyEvent', this.name, 1, 2, 3) } }, } </script> <style scoped> .student{ background-color: pink; padding: 5px; margin-top: 30px; } </style>
2.5 自定义事件只触发一次
实现方法与使用vue的内置事件一样,使用事件修饰符
App.vue
<template> <div class="app"> <h1>{{msg}}</h1> <School :getSchoolName="getSchoolName"></School> <Student @MyEvent.once="getStudentName"></Student> <!-- <Student ref="student"></Student> --> </div> </template> <script> //导入子组件 import Student from './components/Student' import School from './components/School' export default { name: 'App', components: { School, Student }, data() { return { msg: '你好啊!' } }, methods: { getSchoolName(name) { console.log('App收到了学校名:', name) }, getStudentName(name, ...params) { console.log('App收到了学生名:', name) console.log('其他参数:', params) } }, mounted() { // 为子组件 Student 绑定自定义事件 // 自定义事件只被触发一次 // this.$refs.student.$once('MyEvent', this.getStudentName) } } </script> <style scoped> .app { background-color: gray; padding: 5px; } </style>
2.6 解绑自定义事件
解绑自定义事件,需要在被绑定自定义事件的子组件实例对象上进行自定义事件的解绑。
2.6.1 语法
解绑自定义事件,调用被绑定自定义事件的子组件实例对象上的$off()
方法。
this.$off(自定义事件)
2.6.2 解绑一个自定义事件
// 解绑 MyEvent 自定义事件 this.$off('MyEvent')
Student.vue
<template> <div class="student"> <h2>学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> <button @click="sendStudentName">把学生姓名给App</button> <button @click="offEvent">点击解绑自定义事件</button> </div> </template> <script> export default { name:'Student', data() { return { name:'张三', sex:'男' } }, methods: { sendStudentName() { console.log('点击了按钮"把学生姓名给App"') this.$emit('MyEvent', this.name) }, offEvent() { // 解绑 MyEvent 自定义事件 console.log('解绑 MyEvent 自定义事件') this.$off('MyEvent') } }, } </script> <style scoped> .student{ background-color: pink; padding: 5px; margin-top: 30px; } </style>
2.6.3 解绑多个自定义事件
解绑多个自定义事件,需要向
$off()
方法中传入一个数组,数组中的元素为需要解绑的自定义事件的名
// 解绑 MyEvent demo 自定义事件 this.$off(['MyEvent', 'demo'])
App.vue
<template> <div class="app"> <h1>{{msg}}</h1> <School :getSchoolName="getSchoolName"></School> <Student @MyEvent="getStudentName" @demo="demo" ></Student> </div> </template> <script> //导入子组件 import Student from './components/Student' import School from './components/School' export default { name: 'App', components: { School, Student }, data() { return { msg: '你好啊!' } }, methods: { getSchoolName(name) { console.log('App收到了学校名:', name) }, getStudentName(name) { console.log('App收到了学生名:', name) }, demo() { console.log('自定义事件 demo 被触发...') } }, } </script> <style scoped> .app { background-color: gray; padding: 5px; } </style>
Student.vue
<template> <div class="student"> <h2>学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> <button @click="sendStudentName">把学生姓名给App</button> <button @click="offEvent">点击解绑自定义事件</button> </div> </template> <script> export default { name:'Student', data() { return { name:'张三', sex:'男' } }, methods: { sendStudentName() { console.log('触发事件:') this.$emit('MyEvent', this.name) this.$emit('demo') }, offEvent() { // 解绑 MyEvent demo 自定义事件 console.log('解绑 MyEvent demo 自定义事件') this.$off(['MyEvent', 'demo']) } }, } </script> <style scoped> .student{ background-color: pink; padding: 5px; margin-top: 30px; } </style>
2.6.4 解绑所有自定义事件
解绑所有自定义事件,向
$off()
方法中不传入参数即可
// 解绑所有自定义事件 this.$off()
Student.vue
<template> <div class="student"> <h2>学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> <button @click="sendStudentName">把学生姓名给App</button> <button @click="offEvent">点击解绑自定义事件</button> </div> </template> <script> export default { name:'Student', data() { return { name:'张三', sex:'男' } }, methods: { sendStudentName() { console.log('触发事件:') this.$emit('MyEvent', this.name) this.$emit('demo') }, offEvent() { // 解绑 所有 自定义事件 console.log('解绑 所有 自定义事件') this.$off() } }, } </script> <style scoped> .student{ background-color: pink; padding: 5px; margin-top: 30px; } </style>
3. 自定义事件的注意点
3.1 使用 ref 绑定自定义事件中的 this
<template> <div class="app"> <h1>{{msg}} 学生姓名:{{stuName}}</h1> <School :getSchoolName="getSchoolName"></School> <!-- <Student @MyEvent="getStudentName"></Student> --> <Student ref="stu"></Student> </div> </template> <script> //导入子组件 import Student from './components/Student' import School from './components/School' export default { name: 'App', components: { School, Student }, data() { return { msg: '你好啊!', stuName: '' } }, methods: { getSchoolName(name) { console.log('App收到了学校名:', name) }, getStudentName(name) { console.log('App收到了学生名:', name) }, }, mounted() { // 由于vue规定 // 谁触发事件,对应的回调函数中的this就指向谁 // 由于触发自定义事件 MyEvent 为Student组件,且普通函数拥有自己的this // 所以 this 指向 Student组件实例对象 // this.stuName = name 所以相当于向Student组件中的stuName赋值 this.$refs.stu.$on('MyEvent', function(name) { console.log('App收到了学生名:', name) this.stuName = name }) }, } </script> <style scoped> .app { background-color: gray; padding: 5px; } </style>
mounted() { // 由于vue规定 // 谁触发事件,对应的回调函数中的this就指向谁 // 更改为箭头函数 // 由于箭头函数没有自己的this // 所以会在函数声明位置向外查找,即App组件实例对象 // 所以箭头函数 this.stuName = name 就是向 App组件实例对象中的stuName赋值 this.$refs.stu.$on('MyEvent', (name) => { console.log('App收到了学生名:', name) this.stuName = name }) },
<template> <div class="app"> <h1>{{msg}} 学生姓名:{{stuName}}</h1> <School :getSchoolName="getSchoolName"></School> <!-- <Student @MyEvent="getStudentName"></Student> --> <Student ref="stu"></Student> </div> </template> <script> //导入子组件 import Student from './components/Student' import School from './components/School' export default { name: 'App', components: { School, Student }, data() { return { msg: '你好啊!', stuName: '' } }, methods: { getSchoolName(name) { console.log('App收到了学校名:', name) }, getStudentName(name) { console.log('App收到了学生名:', name) this.stuName = name }, }, mounted() { // 此种写法,会先将getStudentName函数中的this指向Student组件实例对象 // 但是由于getStudentName函数声明在App组件的methods中 // 在methods中的方法,this一定指向所在组件的实例对象 // 所以getStudentName中的this最终指向App组件实例对象 this.$refs.stu.$on('MyEvent', this.getStudentName) }, } </script> <style scoped> .app { background-color: gray; padding: 5px; } </style>
3.2 为子组件绑定内置事件
<!-- 这样子绑定内置事件,会被认为是自定义事件,只不过自定义事件名字是click --> <Student ref="stu" @click="show"></Student> • 1 • 2
// App组件 methods show() { alert(11111) }
为子组件绑定内置事件,且不让内置事件被认为是自定义事件,需要使用事件修饰符native
,即可为子组件绑定内置事件。
<Student ref="stu" @click.native="show"></Student>
4. 组件自定义事件 总结
- 一种组件间通信的方式,适用于:子组件 ===> 父组件
- 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。
- 绑定自定义事件:
- 第一种方式,在父组件中:
<Demo @atguigu="test"/>
或<Demo v-on:atguigu="test"/>
- 第二种方式,在父组件中:
<Demo ref="demo"/> ...... mounted(){ this.$refs.xxx.$on('atguigu',this.test) }
- 若想让自定义事件只能触发一次,可以使用
once
修饰符,或$once
方法。
- 触发自定义事件:
this.$emit('atguigu',数据)
- 解绑自定义事件
this.$off('atguigu')
- 组件上也可以绑定原生DOM事件,需要使用
native
修饰符。 - 注意:通过
this.$refs.xxx.$on('atguigu',回调)
绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!