zoukankan      html  css  js  c++  java
  • vue之自行实现派发与广播-dispatch与broadcast

    要解决的问题

    主要针对组件之间的跨级通信

    为什么要自己实现dispatch与broadcast?

    因为在做独立组件开发或库时,最好是不依赖第三方库

    为什么不使用provide与inject?

    因为它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
    然后有两种场景它不能很好的解决:
    父组件向子组件(支持跨级)传递数据;
    子组件向父组件(支持跨级)传递数据。

    代码如下:

    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 {
          // todo 如果 params 是空数组,接收到的会是 undefined
          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);
        }
      }
    };
    
    这里面的核心思想是通过递归或遍历来查找要broadcast或dispatch的组件名字,然后在组件自身上emit与on
    
    
    parent.vue
    
    <template>
      <div>
        <h1>我是父组件</h1>
        <button @click="handleClick">触发事件</button> <child />
      </div>
    </template>
    <script>
    import Emitter from "@/mixins/emitter.js";
    import Child from "./child";
    export default {
      name: "componentA",
      mixins: [Emitter],
      created() {
        this.$on("child-to-p", this.handleChild);
      },
      methods: {
        handleClick() {
          this.broadcast("componentB", "on-message", "Hello Vue.js");
        },
        handleChild(val) {
          alert(val);
        }
      },
      components: {
        Child
      }
    };
    </script>
    
    
    
    child.vue
    
    <template>
      <div>我是子组件</div>
    </template>
    <script>
    import Emitter from "@/mixins/emitter.js";
    export default {
      name: "componentB",
      mixins: [Emitter],
      created() {
        this.$on("on-message", this.showMessage);
        this.dispatch("componentA", "child-to-p", "hello parent");
      },
      methods: {
        showMessage(text) {
          window.alert(text);
        }
      }
    };
    </script>
    
    

    这样就能实现跨级组件自定义通信了,但是,要注意其中一个问题:订阅必须先于发布,也就是说先有on再有emit

    父子组件渲染顺序,实例创建顺序

    子组件先于父组件前渲染,所以在子组的mounted派发事件时,在父组件中的mounte中是监听不到的。
    而父组件的create是先于子组件的,所以可以在父组件中的create可以监听到
    
    
  • 相关阅读:
    SQL语句
    POJ2586——Y2K Accounting Bug
    POJ1328——Radar Installation
    POJ2965——The Pilots Brothers' refrigerator
    SDIBT2666——逆波兰表达式求值
    POJ1753——Flip Game
    Python全栈开发-有趣的小程序
    跑马灯效果、jquery封装、$.fn和$.extend方法使用
    js 实现浏览器全屏效果
    百度地图点聚合功能如何提高性能
  • 原文地址:https://www.cnblogs.com/raind/p/10241720.html
Copyright © 2011-2022 走看看