今天向大家介绍另外一种组件之间通信的方法,也就是 findComponents 系列方法,它并非Vue.js内置,而是需要自行实现的,我们以工具函数的形式来使用,它是一系列的函数,可以说是组件通信的终极方案。findComponents 系列方法最终都是返回组件的实例,进而可以读取或调用该组件的数据和方法。
它的适用场景:
--由一个组件,向上找到最近的指定组件
--由一个组件,向上找到所有的指定组件
--由一个组件,向下找到最近的指定组件
--由一个组件,向下找到所有的的指定组件
--由一个组件,找到指定组件的兄弟组件
实现:
5个函数的原理,都是通过递归、遍历找到指定组件的name选项匹配的组件实例并返回
1. 向上找到最近的指定组件——findComponentUpward
//1.向上找到指定的组件实例
function findComponentUpward(context,componentName){
let parent=context.$parent;
let name=parent.$options.name;
while(parent && (!name || [componentName].indexOf(name) < 0)){
parent =parent.$parent;
if(parent){
name=parent.$options.name;
}
}
return parent;
}
findComponentUpward 接收两个参数,第一个是当前上下文,比如你要基于哪个组件来向上寻找,一般都是基于当前的组件,也就是传入 `this`;第二个参数是要找的组件的 `name` 。
findComponentUpward 方法会在 while 语句里不断向上覆盖当前的 `parent` 对象,通过判断组件(即 parent)的 name 与传入的 componentName 是否一致,直到最近的一个组件为止。
与 dispatch 不同的是,findComponentUpward 是直接拿到组件的实例,而非通过事件通知组件。比如下面的示例
//父组件
<template>
<div>
<h1>父组件</h1>
<C></C>
</div>
</template>
<script>
import C from './c1.vue';
export default {
name:'p1',
data(){
return {
px:'我是父级数据'
}
},
components:{
C
}
}
</script>
<style scoped>
</style>
<template>
<div>
<h1>子组件</h1>
</div>
</template>
<script>
import {findComponentUpward} from './emitter.js/emitter.js';
export default {
name:'c1',
data(){
return {
}
},
mounted(){
//comA就是找到的父级组件实例,可以调用其任何方法
const comA=findComponentUpward(this,'p1');
if(comA){
console.log(comA.px) //我是父级数据
}
}
}
</script>
<style scoped>
</style>
2.向上找到所有的指定组件——findComponentsUpward
function findComponentsUpward (context, componentName) {
let parents = [];
const parent = context.$parent;
if (parent) {
if (parent.$options.name === componentName) parents.push(parent);
return parents.concat(findComponentsUpward(parent, componentName));
} else {
return [];
}
}
export { findComponentsUpward };
3.向下找到最近的指定组件——findComponentDownward
function findComponentDownward(context,componentName){
const childrens=context.$children; //数组
let children=null;
if(childrens.length){
for(const child of childrens){
const name=child.$options.name;
if(name===componentName){
children=child;
break;
}else{
children=findComponentDownward(child,componentName);
if(children){
break;
}
}
}
}
return children;
}
export {findComponentDownward}
context.$children` 得到的是当前组件的全部子组件,所以需要遍历一遍,找到有没有匹配到的组件 `name`,如果没找到,继续递归找每个 $children 的 $children,直到找到最近的一个为止。
4.向下找到所有指定的组件——findComponentsDownward
function findComponentsDownward (context, componentName) {
return context.$children.reduce((components, child) => {
if (child.$options.name === componentName) components.push(child);
const foundChilds = findComponentsDownward(child, componentName);
return components.concat(foundChilds);
}, []);
}
export { findComponentsDownward };
这个函数实现的方式有很多,这里巧妙使用 `reduce` 做累加器,并用递归将找到的组件合并为一个数组并返回,代码量较少,但理解起来稍困难。这篇文章详细介绍了reduce的用法,供大家参考:https://www.jianshu.com/p/e375ba1cfc47
5.找到指定组件的兄弟组件——findBrothersComponents
function findBrothersComponents (context, componentName, exceptMe = true) {
let res = context.$parent.$children.filter(item => {
return item.$options.name === componentName; //返回所有item.$options.name === componentName的item
});
let index = res.findIndex(item => item._uid === context._uid); //findIndex() 方法返回传入一个测试条件(函数)符合条件的数组第一个元素位置。
if (exceptMe) res.splice(index, 1);
return res;
}
export { findBrothersComponents };
比其它 4 个函数,findBrothersComponents 多了一个参数 `exceptMe`,是否把本身除外,默认是 true。寻找兄弟组件的方法,是先获取 `context.$parent.$children`,也就是父组件的全部子组件,这里面当前包含了本身,所有也会有第三个参数 exceptMe。Vue.js 在渲染组件时,都会给每个组件加一个内置的属性 `_uid`,这个 _uid 是不会重复的,借此我们可以从一系列兄弟组件中把自己排除掉。
本文章由作者搜集整理,并非原创
本文介绍了一种Vue组件间通信的方法——findComponents系列函数,包括向上、向下查找指定组件及查找兄弟组件等五个实用函数,提供了具体实现代码及应用场景示例。
2771

被折叠的 条评论
为什么被折叠?



