//这里面的核心思想是通过递归或遍历来查找要broadcast或dispatch的组件名字,然后在组件自身上emit与on


function broadcast(componentName, eventName, params) {
  this.$children.forEach(child => {
    var name = child.$options.componentName;

    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) {
        console.log('--------向上转发', componentName, eventName, params)
      var parent = this.$parent || this.$root;
      var name = parent.$options.componentName;

      while (parent && (!name || name !== componentName)) {
        parent = parent.$parent;

        if (parent) {
          name = parent.$options.componentName;
        }
      }
      if (parent) {
        parent.$emit.apply(parent, [eventName].concat(params));
      }
    },
    broadcast(componentName, eventName, params) {
      console.log('--------向下广播', componentName, eventName, params)
      broadcast.call(this, componentName, eventName, params);
    }
  }
};

相信看过element源码和自己封装组件库的同学们对上面的代码一定不陌生

该js是提供方法给其他组件做混入使用的。他对外有dispatch和broadcast两个接口,从命名和参数等方面,这两个方法应该大致是用来处理一些各层级之间事件的,也就是通信。

一、dispatch

dispatch方法有三个参数,

  • componentName,表示组件名称,用于匹配正确到正确的组件名。
  • eventName,事件名,需要触发的事件
  • params,参数,触发时带入的参数

前两行,用于查找到当前元素的父组件,如果没有就使用根节点,并取父组件的组件名用于后期匹配。

紧接着的是一个while循环,用于循环父组件,直到找到或者到达根元素,匹配不到。

  1. while (parent && (!name || name !== componentName)) {
  2. parent = parent.$parent;
  3.  
  4.     if (parent) {
  5. name = parent.$options.componentName;
  6. }
  7. }

循环过程中不断记录组件名,用于判断是否找到。

最后一部分是,当有匹配到的父组件时,就去触发父组件的对应的事件函数

  1. if (parent) {
  2.   parent.$emit.apply(parent,[eventName].concat(params));
  3. }

接下来看下broadcast函数

二、broadcast

将emitter内部定义的一个broadcast函数利用call改变this指向。

broadcast内直接对子组件进行遍历,当匹配到对应的组件名时,则去触发对应子组件的对应事件。如果没有,则递归继续查找子组件。

注:我们会发现每条向下传播的线路只要触发了一次对应的事件,就不会再向下传递了。

带注释的源码:emitter.js

element-ui中的事件传播就是这样的了,让我想到了angular中的$broadcast和$emit事件。

三、demo运用理解

<div class="home">
    <HelloWorld msg="Welcome to Your Vue.js App" @clickFun="handleEvent"/>
    <s-input v-model="txt" type="input"></s-input>
    <button @click="test2">父组件的按钮dispatch</button>
  </div>
test2(){
      this.broadcast('SButton','test','子组件触发dispatch事件---')  
//三个参数分别是
componentName,表
示组件名称,用于匹配正确到正确的组件名。eventName,事件名,需要触发的事件params,参数,触发时带入的参数
// console.log('vue2已经废弃')
    }

点击父组件的按钮调用test2的方法开始向下广播

找到子组件

 

 

 

 

点击按钮调用test1的方法开始向上转发

 

 

 

 

posted on 2021-04-11 18:18  白不了的黑发  阅读(531)  评论(0编辑  收藏  举报