自定义事件与事件总线
目录1. 事件
1.1 基本使用
-
使用
v-on:xxx
或@xxx
绑定事件,其中xxx是事件名 -
事件的回调需要配置在methods对象中,最终会在vm上
-
methods中配置的函数,都是被Vue所管理的函数,this指向的是vm或组件实例对象
-
@click="demo"
和@click="demo($event)"
效果一致,但后者可以传递额外参数<div id="root"> <button @click="showInfo1">点击获取提示信息1</button> <button @click="showInfo2(66,"hi",$event)">点击获取提示信息2</button> </div>
<script> const vm = new Vue({ el:'#root', data:{ name:"Jack" }, method:{ showInfo(event){ alert('hi') }, showInfo2(String,number,event){ alert(String) } } }) </script>
1.2 事件修饰符
-
prevent:阻止默认事件(常用)
-
stop:阻止事件冒泡(常用)
-
once:事件只触发一次(常用)
-
capture:使用事件的捕获模式
-
self:只有event.target是当前操作的元素才触发事件
-
passive:事件的默认行为立即执行,无需等待事件回调执行完毕
<div id="root"> <div class="demo1" @click="showInfo"> <!--原来点击超链接会在提示信息后跳转,现在不会跳转--> <a href="https://www.baidu.com/" @click.prevent="showInfo">点击提示信息</a> <!--原来点击后,由于冒泡会提示两次,现在只会提示一次--> <button @click.stop="showInfo">点击提示信息</button> <!--事件只触发一次--> <button @click.once="showInfo">点我提示信息</button> <!--链式修饰--> <button @click.once.prevent.stop="showInfo">点我提示信息</button> </div> </div>
1.3 键盘事件
-
Vue中常用的按键别名:
回车 Enter 删除 delete 退出 Esc 空格 Space 换行 tab 上 up 下 down 左 left 右 right -
Vue未提供别名的按键,可以使用按键原始的key值去绑定,但是注意要转为kebab-case(短横线命名)
- 比如
CAPS LOCKS
键,就要书写为caps-locks
- 比如
-
系统修饰键
系统修饰键包含:ctrl、alt、shift、meta,它们的使用方法比较特殊
- 配合keyup使用:按下修饰键的同时,再按下其它键,随后释放其它键,事件才会被触发
- 配合keydown使用:正常触发事件
-
Vue.config.keyCodes.自定义键名 = 键码
可以去定制按键别名<div id="root"> <!--按下回车键执行showInfo1方法--> <input type="text" @keydown.enter="showInfo1"> <!--同时按下ctrl键和y键执行showInfo2方法--> <input type="text" @keyup.ctrl.y="showInfo2"> </div>
2. 自定义事件
-
自定义事件是一种组件间通信的方式,适用于子组件传递数据给父组件
如果子组件想给父组件传数据,那么就要在父组件中给子组件绑定自定义组件
-
基本流程:子组件 → 子组件想传递数据给子组件 → 父组件绑定监听方法给子组件 → 子组件接收并调用监听方法,同时传参 → 父组件接收到参数,使用参数与监听方法 → 父组件
-
绑定自定义事件
-
方法一:在父组件中
<Demo @事件名="方法名"/>
<!--EventName是之后子组件中需要调用的事件名 demo是父组件中(希望子组件调用的)用于监听的方法名--> <Student v-on:EventName="demo"/> <!--简写形式--> <Student @EventName="demo"/>
-
方法二:在父组件中
this.$refs.demo.$on('事件名',回调函数)
<Student ref="student"/> ..... <script> .... mounted(){ /*this.$refs.student是为了为了获取到student的组件实例 $on是为了绑定,EventName是之后子组件中需要调用的事件名 this.getStudentName是父组件中(希望子组件调用的)用于监听的方法名*/ this.$refs.student.$on('EventName',this.getStudentName) } </script>
-
注意事项:
- 通过
this.$refs.xxx.$on('事件名',回调函数)
绑定自定义事件时,回调函数要么配置在methods中,要么使用箭头函数,否则this指向会出问题 - 自定义事件依旧适用事件修饰符,如
<Student @EventName.once="demo"/>
- 如果尝试在组件上绑定原生事件会产生冲突,如
<Student @click="demo"/>
,这样被会识别为自定义事件而无法触发click本来的效果。如果要恢复click的效果,需要使用.native
,<Student @click.native="demo"/>
- 通过组件名直接绑定与通过
$on
没什么区别,不过$on
也可以在子组件中自己调用,这样就可以自己监听自己的函数了
- 通过
-
-
触发自定义事件:
this.$emit('事件名',数据)
-
当确定父组件已经正常绑定事件到子组件后,子组件就可以通过
$emit
在任意地方调用父组件的方法 -
调用后该事件会被父组件监听到,调用时可以传递参数
<button @click="sendStudentName">传递学生名给父组件</button> <script> //... methods:{ sendStudentName(){ this.$emit('atguigu',this.name) } } </script>
-
-
解绑自定义事件:
this.$off('事件名')
//解绑在子组件中进行 this.$off('EventName') //解绑单个事件 this.$off(['EventName1','EventName2']) //解绑多个事件 this.$off() //解绑所有事件
注意:所有绑定的自定义事件在组件销毁时都会自动解绑
3. 全局事件总线
-
全局事件总线是一种可以在任意组件间通信的方式,本质上是一个对象
它满足以下要求:
- 所有的组件对象都必须能看见它
- 这个对象必须能够绑定,触发和解绑事件
-
全局事件总线的原理与Vuex的原理有异曲同工之妙,Vuex的做法是抽离出一个js文件作为共用空间,而事件总线相对隐蔽一些——将Vue实例(vm)的原型对象上安装一个
$bus
作为公用空间。只要其它组件有需要,就可以用$on
往$bus
上绑事件,然后需要回传参数的组件再用$emit
传递即可 -
安装全局事件总线
new Vue({ //... beforeCreate(){ Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm }, //... })
-
使用事件总线
-
接收数据:若A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身
methods(){ demo(data){...} } //... mounted(){ this.$bus.$on('xxxx',this.demo) }
-
提供数据
this.$bus.$emit('xxx',load)
-