$on與$emit實現父子跨多元件通訊
阿新 • • 發佈:2019-05-15
眾所周知,
$on
是做事件監聽,$emit
是做事件的派發,但對於$dispatch
和$broadcast
大家可能就比較陌生了,這對api是vue1.x版本的,在vue2.x裡已經被廢棄
$on
和$emit
- $on對於自身觸發的事件,也是可以監聽的
$dispatch
與 $broadcast
$dispatch
:用於向上級派發事件,只要是它的父級(一級或多級以上),都可以在元件內通過$on
監聽到$broadcast
: 用於向下級派發事件,只要是它的子元件,都可以在元件內通過$on
監聽到
如何通過
$on
和$emit
來實現$dispatch
和$broadcast
,思路大概是,向上遞迴查詢要通訊的元件,或者向下,我們將該功能程式碼提到mixin中,方便各元件複用
// emitter.js const broadcast = function(comName,event,data) { this.$children.forEach(p =>{ if(p.$options.name === comName) { p.$emit(event, data) } else{ broadcast.apply(p,comName,event,data) } }) } methods: { /** * comName 目標元件 * event 事件名 * data 要傳的資料 */ broadcast(comName,event,data) { broadcast.call(this, arguments) }, dispatch (comName,event,data) { let parent = this.$parent || this.$root; let name = parent.$options.name; // 這裡是找最接近的父元件 while (parent && (!name || name !== componentName)) { parent = parent.$parent; if (parent) { name = parent.$options.name; } } if (parent) { parent.$emit.apply(parent, [eventName].concat(params)); } }, }
使用案例
// 父元件A,省略部分程式碼 <template> <button @click="handleClick">觸發事件</button> </template> <script> import Emitter from '../mixins/emitter.js'; export default { name: 'componentA', mixins: [ Emitter ], methods: { handleClick () { this.broadcast('componentB', 'sendMsg', 'Hello 我是父元件A'); } } } </script> // 子元件B,省略部分程式碼 <script> import Emitter from '../mixins/emitter.js'; export default { name: 'componentB', mixins: [ Emitter ], // 在created或者mounted做事件監聽 created () { this.$on('sendMsg', this.showMsg) }, methods: { showMsg (data) { alert(data) } } } </script>
和原來的api的區別
- 需要額外傳入元件的 name 作為第一個引數;
- 無冒泡機制;
- 第三個引數傳遞的資料,只能是一個(較多時可以傳入一個物件),而 Vue.js 1.x 可以傳入多個引數,當然,你對 emitter.js 稍作修改,也能支援傳入多個引數,只是一般場景傳入一