在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'