Recently, I began to learn VUE in depth to help me to advance to higher levels, so as to record what I learned so as not to forget it later.

Basics (VUE API)

  1. Props of the father the son
  2. $emit son father
  3. provide & inject

Improve paper

1. Descendants communicate with ancestors

1. Without further words, start to implement the descendant component to the ancestor component one-way transmission of data (need to add $ON event listener in the ancestor component)

functiondispatch(componentName, eventName, ... params) {let parant = this.$parent || this.$root;
  let parentName = parant.$options.name;
  while(parant && (! parentName && parentName ! == componentName)) { parent = parent.$parent;
    if (parent) {
      parentName = parent.$options.name; }}if (parent) {
    parent.$emit.apply(parent, [eventName].concat(params)); }}Copy the code

Note: This refers to the strength of the current VUE component. If this is not implemented in a mixin way, you need to manually change the reference to this when calling.

2. Of course, the above method only sends a message to itself through the parent component, so if you want to get the first parent that matches the condition, then you need to do a little bit of processing

function findComponentUpward(context, componentName) {
  let parent = context.$parent;
  let parentName = parent.$options.name;
  while(parent && (! parentName || parentName ! == componentName)) { parent = parent.$parent;
    if (parent) {
      parentName = parent.$options.name; }}return parent;
}
Copy the code

3. Go one step further and get all the parent components that meet the criteria

function findComponentsUpward(context, componentName) {
  const parents = [];
  let parent = context.$parent;
  if (parent) {
    if (parent.$options.name == componentName) {
      parents.push(parent);
    }
    const nextParent = findComponentsUpward(parent, componentName);
    parents.concat(nextParent);
  }
  return parents;
}
Copy the code

Ancestors communicate with their descendants

1. Similar to the implementation of communication between descendants and ancestors, using the method of broadcast for reference (need to add $ON event listener in the ancestor component)

functionbroadcast(componentName, eventName, ... params) { this.$children.forEach(child => {
    const childName = child.$options.name;
    if (childName === componentName) {
      child.$emit.apply(child, [eventName].concat(params));
    } else {
      broadcast.call(child, componentName, eventName, ...params);
    }
  });
}
Copy the code

2. With a little improvement, it is possible to obtain qualified sub-components, of course, not necessarily direct sub-components

function findComponentDownward(context, componentName) {
  const children = context.$children;
  let childComponent;

  if (children.length) {
    for (let child of children) {
      const childName = child.$options.name;
      if (childName === componentName) {
        childComponent = child;
        break;
      } else {
        childComponent = findComponentDownward(child, componentName);
        if (childComponent) {
          break; }}}}return childComponent;
}
Copy the code

Note: $children is not guaranteed to be sequential, and there is no guarantee that the results of multiple executions of the same condition will be consistent.

3. Further expand to achieve the acquisition of all eligible sub-components

function findComponentsDownward(context, componentName) {
  return context.$children.reduce((childComponents, child) => {
    if (child.$options.name === componentName) {
      childComponents.push(child);
    }
    const nextChildComponents = findComponentsDownward(child, componentName);
    returnchildComponents.concat(nextChildComponents); } []); }Copy the code

3. Component Communication without Correlation (eventBus)

My implementation draws on some of the essence of vue source event to implement (sure enough, or standing on the shoulders of giants to see further)

class EventBus {
  constructor() {
    this.eventQueues = {}
  }
  
  on(event, fn) {
    if (Array.isArray(event)) {
      for (leti = 0, l = event.length; i < l; i++) { this.on(event[i], fn); }}else{ (this.eventQueues[event] || (this.eventQueues[event] = [])).push(fn); } } emit(event, ... params) { const events = this.eventQueues[event];if (events) {
      for (let i = 0, l = events.length; i < l; i++) {
        events[i].apply(this, params);
      }
    }
  }
  
  off(event, fn) {
    if(! arguments.length) { this.eventQueues = Object.create(null);return;
    }
    if (Array.isArray(event)) {
      for (let i = 0, l = event.length; i < l; i++) {
        this.off(event[i], fn);
      }
      return;
    }
    if(! fn) { this.eventQueues[event] = null; } const cbs = vm._events[event]let cb;
    let i = cbs.length;
    while (i--) {
      cb = cbs[i];
      if (cb === fn) {
        cbs.splice(i, 1);
        break; }}}}Copy the code
Well, that’s it for the record this time. These are all the ways I can think of to communicate between components in VUE. If there are any deficiencies or mistakes, please give advice; In addition, I am also looking forward to having a partner with me in the study of the road to progress together. Of course, I’d love to play a king.