Detailed explanation of vue self distributed and broadcast of dispatch and broadcast

  • 2021-10-24 18:57:02
  • OfStack

Problems to be solved

Mainly for cross-level communication between components

Why do you want to implement dispatch and broadcast yourself?

Because it is best not to rely on the third-party library when doing independent component development or library

Why not use provide and inject?

Because of its usage scenario, subcomponents mainly obtain the state of superior components, and a relationship between active provision and dependency injection is established among cross-level components.
Then there are two scenarios that it can't solve well:
Parent components pass data to child components (cross-level support);
Child components pass data to parent components (cross-level support).

The code is as follows:

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  If  params  Is an empty array, the received is  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);
  }
 }
};

parent.vue


<template>
 <div>
  <h1> I am the parent component </h1>
  <button @click="handleClick"> Trigger event </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> I am a subcomponent </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>

This enables custom communication across levels of components, but be aware of one problem: Subscription must precede publication, that is, on followed by emit

Parent-child component rendering order, instance creation order

The child component is rendered before the parent component, so when the mounted of the child group distributes events, it is not listenable in the mounte of the parent component.
The create of the parent component is prior to the child component, so the create in the parent component can listen


Related articles: