不用vuex的情况下,隔代组件间的通信

优点:适合开发层级不会很复杂的独立组件,无需借助vuex

缺点:依赖组件树的结构,比如需要知道A和B谁是父,谁是子,然后父中broadcast,子中dispatch。


先列一个简单的case:


export default {
  methods: {
    handleEmitEvent () {
      this.$emit('test', 'Hello Vue.js')
    }
  }
}
复制代码



复制代码

子组件触发($emit),父组件监听($on)。

So, 既然是子组件自己触发的,那它自己也可以监听到, 即组件自己监听自己的emit。



复制代码

乍一看多次一举, handleEmitEvent可以直接写逻辑,没必要emit,on这样绕了一圈

如果handleEmitEvent不是通过该组件自身调用的呢?

设想这样的场景,A是父组件,B是子组件,中间可能跨多级。 A向B通信:




复制代码


复制代码

事件触发点是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…

转载于:https://juejin.im/post/5caf64e25188251acc538f9c

你可能感兴趣的:(不用vuex的情况下,隔代组件间的通信)