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)
- Props of the father the son
- $emit son father
- 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