vue2中$emit $on $off实现组件之间的联动,绝对有你想了解的
在vue2开发中,你肯定会遇到组件之间联动的问题,现在我们就来说说哪个神奇的指令可以满足我们的需求。
一、先上实例:
需求:点击A组件或者B组件可以使C组件的名称相应发生改变,同样,点击A组件也会使对应的B或者C组件显示选中状态。
二、说一说$emit、 $on 、$off
1、vm.$on( event, callback )
监听当前实例上的自定义事件。事件可以由vm.$emit触发。回调函数会接收所有传入事件触发函数的额外参数。
2、vm.$emit( event, […args] )
触发当前实例上的事件。附加参数都会传给监听器回调,如果没有参数,形式为vm.$emit(event)
3、vm.$off( [event, callback] )
移除自定义事件监听器。
- 如果没有提供参数,则移除所有的事件监听器;
- 如果只提供了事件,则移除该事件所有的监听器;
- 如果同时提供了事件与回调,则只移除这个回调的监听器。
三、图示代码实现
点击A组件,B或C组件相应改变(请注意代码中的EventBus对象,文末会进行解释,听哀家一句劝,少踩十年坑)
A组件部分代码:
A组件HTML
<el-submenu index="3"> <template slot="title">{{SelectPro}}</template> <el-menu-item :index="item.number" v-for="(item,index) in ProjectList" :key="index" @click="proClickHandler(item.name,item.ProjectId)">{{item.name}} </el-menu-item> </el-submenu>
A组件js
1 EventBus.$emit('refreshPro');
B组件部分代码:
B组件HTML
1 <el-container> 2 <el-aside width="100%">项目 3 <table> 4 <tr> 5 <td v-for="itemPro in ProjectArr" style="padding-right:10px"> 6 <div :id= "itemPro.projectId" class="tableTypeItem" style="padding: 10px;width:180px;text-align: left;background-color: #eeeeee" @click="objClickHandler(itemPro.name,itemPro.projectId)"> 7 <div style="height:10px;border-bottom: 2px #000000"> 8 <a>{{itemPro.name}}</a> 9 </div> 10 <hr class="line"/> 11 <div style="padding:10px 0"> 12 <a>{{itemPro.time}}</a> 13 <br> 14 <br> 15 <a>{{itemPro.user}}</a> 16 </div> 17 </div> 18 </td> 19 </tr> 20 </table> 21 </el-aside> 22 <!--<el-main>全部项目--> 23 <!--</el-main>--> 24 </el-container>
B组件js
1 mounted(){ 2 var _self = this; 3 EventBus.$on('refreshPro', function () { 4 _self.changeColor(); 5 _self.GetRecord(); 6 _self.$refs.pie.GetPerInstance(); 7 _self.$refs.bar.GetInstance(); 8 }) 9 }, 10 destroyed: function() { 11 EventBus.$off('refreshPro'); 12 }
点击B或者C组件,A组件相应改变:
实现原理为将A组件的数据放到vuex中进行状态管理,当vuex中的数据改变时,computed的钩子函数触发自定义的SelectPro()方法改变A组件的显示名称。
A组件代码
1 computed: { 2 SelectPro() { 3 return this.$store.getters.ProjectName 4 } 5 }
四、切勿忘记的公共实例,大坑,勿踩!
网上百度千篇一律全是使用$emit来实现,但是有一个大坑没有给别人说明,开始我都按照搜索的结果进行操作,都会出现子组件$emit后父组件没有监听到函数的变化,研究了好久才发现$emit和$on的事件必须使用一个空的 Vue 实例作为中央事件总线的实例上,才能够触发。即上述代码中的EventBus。
代码: eventbus.js
1 import Vue from 'vue' 2 3 //消息总线 4 export default new Vue();
A、B组件中引入eventbus.js文件
1 import EventBus from '../../EventBus.js'