组件自定义事件
区别于js内置事件,内置事件是给html元素用的,而自定义事件是给组件用的
1. 给组件实例对象绑定
自定义事件
- 给组件绑定自定义事件
v-on:自定义事件名="回调函数"
比如:<Student v-on:atguigu="demo"/>
上面代码的含义为:由于v-on是在Student这个组件标签上,所以是给student组件的实例对象身上绑定了一个事件,事件名称是atguigu,如果有人触发了这个事件,回调函数demo就会被调用
- 如何触发自定义事件
原则:给谁绑的事件,就找谁触发事件
触发:vc.$emit("自定义事件名")
触发时传递数据:vc.$emit("自定义事件名", 数据...)
- 实现子组件给父组件传递数据的几种方式
<!-- 通过父组件给子组件传递函数类型的props【传递的是一个函数】实现:子给父传递数据 -->
<School :getSchoolName="getSchoolName"/>
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on) -->
<Student @atguigu="getStudentName"/>
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) -->
<Student ref="student"/>
- 通过props实现子组件给父组件传递数据和通过自定义事件实现子组件给父组件传递数据的区别
第一种方式需要子组件接收并亲自调用回调函数,第二种方式只需要绑定事件时设置好回调函数,子组件中触发事件即可
-
绑定自定义事件的两种方式:这两种方式的不同体现在自定义事件绑定方式的不同,触发方式是相同的
第一种方式,使用@或v-on
<!--父组件-->
<Student @atguigu="getStudentName"/>
methods:{
//atguigu事件的回调中能够接收到子组件触发事件时传递的数据
getStudentName(name,x,y){
console.log('demo被调用了', name,x,y)
}
}
<!--子组件-->
<button type="button" @click="sendStudentNameToApp">传递数据给父组件</button>
methods:{
sendStudentNameToApp(){
//通过vc.$emit触发绑定的atguigu事件并进行传参
this.$emit('atguigu',this.name,'a',true)
}
}
第二种方式,使用ref,灵活性强,支持异步操作【定时器、Ajax请求】
<!--父组件-->
<Student ref="student"/>
methods:{
getStudentName(name,x,y){
console.log('demo被调用了', name,x,y)
}
},
mounted() {
//挂载时拿到子组件的组件实例对象进行atguigu事件及回调的绑定
this.$refs.student.$on('atguigu',this.demo)
// setTimeout(()=>{
// this.$refs.student.$on('atguigu',this.demo)
// }, 3000)
}
<!--子组件-->
<button type="button" @click="sendStudentNameToApp">传递数据给父组件</button>
methods:{
sendStudentNameToApp(){
//通过vc.$emit触发绑定的atguigu事件并进行传参
this.$emit('atguigu',this.name,'a',true)
}
}
- 自定义事件仅触发一次就不再触发
1)使用@或v-on进行绑定的要使用事件修饰符once
<Student @atguigu.once="demo"/>
2)使用ref进行绑定的要使用this.$refs.student.$once()
this.$refs.student.$once('atguigu',this.demo)
- 自定义事件触发时传递了多个参数,回调函数中如何接收?
1)自定义事件触发时有多少个参数就传多少个参数,回调函数中按相同的数量进行接收【基本不用】
2)将自定义事件触发时传递的参数封装为一个对象
3)回调函数中使用 demo(name, ...params) 进行接收,name为收到的第一个参数,其余所有参数封装到params中,params是一个数组【ES6语法】
注:params并不是固定的参数名,其他任何名字都可,只不过常用该名字
2. 给组件实例对象解绑
自定义事件
如果一个组件实例对象身上的某个自定义事件不再用了,可以进行解绑
- 如何解绑自定义事件
原则:给谁绑的事件,就找谁解绑事件
解绑自定义事件
methods:{
sendStudentNameToApp(){
this.$emit('atguigu',this.name,'a',true)
},
unbind(){
this.$off('atguigu') //解绑一个自定义事件
this.$off(['atguigu','demo']) //解绑多个自定义事件
this.$off() //解绑所有的自定义事件
}
}
回调函数:只要某个事件被触发了,就会调用指定的函数
vm和vc都能用生命周期钩子
一个组件如果被销毁了,那么该组件身上的所有自定义事件也就失效了
如果vm被销毁了,那么vm的所有子组件也就都销毁了,因此子组件身上的所有自定义事件也就失效了
遇到一个问题:
销毁组件实例对象vc或vm后,原生DOM事件也不能用了
3. 两个注意点
computed中可以使用props接收到的数据
使用ref绑定自定义事件时,能不能直接将自定义事件回调函数的定义写在this.$refs.student.$on方法的参数上
谁触发的事件【this.$emit()在哪个组件中调用的】,事件的回调函数当中的this就是谁
组件除了使用自定义事件以外,能不能使用原生DOM事件?
组件标签默认标注的事件名都是自定义事件,哪怕标注的事件名与原生DOM事件相同,Vue也认为是自定义事件;通过native修饰符【译为原生的】可以让组件标签使用原生DOM事件,使用native修饰符后,事件就相当于绑定在了组件的最外层元素上
<!--App组件-->
<Student ref="student" @click.native="m1"/>
methods:{
m1(){
console.log('m1被调用了')
}
}
<!--Student组件-->
<!--相当于click事件绑定在了最外层的div上-->
<template>
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<h2>当前number的值:{{number}}</h2>
<button type="button" @click="changeNumber">number的值++</button>
<button type="button" @click="sendStudentNameToApp">传递数据给父组件</button>
<button type="button" @click="unbind">解绑事件</button>
<button type="button" @click="death">销毁Student组件实例对象</button>
</div>
</template>
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指向会出问题!
全局事件总线是基于自定义事件的
借助Vue开发者工具,可以查看自定义事件
只要有事件被触发时,下面的界面就会有事件的详细信息
注:source项实际就是指组件的实例对象,如果是<Root>组件就是vm
父亲给儿子一个函数,是要儿子调用的
标签:触发,Vue,CLI,自定义,绑定,事件,atguigu,组件 From: https://www.cnblogs.com/wzzzj/p/18039997