提要
在当前组件使用$on监听$emit事件,$on事件有时不确定何时会触发事件,一般会在mounted或created钩子中来监听。
实现dispatch 和 broadcast方法
- 在子组件调用dispatch方法,向上级指定的组件实例(最近的)上出发自定义事件,并传递数据,且该上级组件已预先通过$on监听了这个事件;
- 在父组件调用broadcast方法,向下级指定的组件实例(最近的)上触发自定义事件,并传递数据,且该下级组件已预先通过$on监听了这个事件。
emitter.js
function broadcast(componentName, eventName, params) {
this.$children.forEach(child => {
const name = child.$options.name;
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params));
} else {
broadcast.apply(child, [componentName, eventName].concat([params]));
}
});
}
export default {
methods: {
// 向上派发自定义事件
dispatch(componentName, eventName, params) {
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(parent));
}
},
// 向下广播自定义事件
broadcast(componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params);
},
}
}
实例
<!-- A.vue -->
<template>
<button @click="handleClick">触发事件</button>
</template>
<script>
import Emitter from '../mixins/emitter.js';
export default {
name: 'componentA',
mixins: [Emitter],
methods: {
handleClick () {
this.broadcast('componentB', 'on-message', 'hello Vue.js');
}
}
}
</script>
<!-- B.vue -->
<script>
export default {
name: 'componentB',
created () {
this.$on('on-message', this.showMessage);
},
methods: {
showMessage (text) {
window.alert(text);
}
}
}
</script>
同理,如果B向A通信,在B中调用dispatch方法,在A中使用$on监听事件即可。