优点:适合开发层级不会很复杂的独立组件,无需借助vuex
缺点:依赖组件树的结构,比如需要知道A和B谁是父,谁是子,然后父中broadcast,子中dispatch。
先列一个简单的case:
export default {
methods: {
handleEmitEvent () {
this.$emit('test', 'Hello Vue.js')
}
}
}
复制代码
test="handleEvent">
复制代码
子组件触发($emit),父组件监听($on)。
So, 既然是子组件自己触发的,那它自己也可以监听到, 即组件自己监听自己的emit。
复制代码
乍一看多次一举, handleEmitEvent可以直接写逻辑,没必要emit,on这样绕了一圈
如果handleEmitEvent不是通过该组件自身调用的呢?
设想这样的场景,A是父组件,B是子组件,中间可能跨多级。 A向B通信:
"handleFocus">触发事件 />
复制代码
复制代码
事件触发点是A组件中的input被focus,但是为什么B组件中可以监听到呢?
看完下面Emitter的实现就明白了。
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(params));
}
},
broadcast(componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params);
}
}
};
复制代码
通过mixins可以将dispatch和broadcast方法merge到A组件中,
broadcast就是向下递归遍历通过name寻找指定的组件(componentB), dispatch同理。
实际上最终还是在找到的B中调用$emit触发自定义事件,所以B也就可以监听到该事件的触发,
但是事件的源头却是从A触发,也就实现了A和B的通信。
参考 Vue.js组件精讲 juejin.im/book/5bc844…
注:emitter.js 参考 github.com/iview/iview…