vue组件通信3-findComponent系列方法

组件的通信 3:找到任意组件实例——findComponents 系列方法

provide / inject 和 dispatch / broadcast。它们有各自的使用场景和局限,比如前者多用于子组件获取父组件的状态,后者常用于父子组件间通过自定义事件通信。

findComponents 系列方法,它并非 Vue.js 内置,而是需要自行实现,以工具函数的形式来使用,它是一系列的函数,可以说是组件通信的终极方案。findComponents 系列方法最终都是返回组件的实例,进而可以读取或调用该组件的数据和方法。

5 个不同的函数:

  • 由一个组件,向上找到最近的指定组件;
  • 由一个组件,向上找到所有的指定组件;
  • 由一个组件,向下找到最近的指定组件;
  • 由一个组件,向下找到所有指定的组件;
  • 由一个组件,找到指定组件的兄弟组件。

实现

5 个函数的原理,都是通过递归、遍历,找到指定组件的 name 选项匹配的组件实例并返回。

向上找到最近的指定组件——findComponentUpward

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// assist.js
// 由一个组件,向上找到最近的指定组件
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
}
export { findComponentUpward }

findComponentUpward 接收两个参数,第一个是当前上下文,比如你要基于哪个组件来向上寻找,一般都是基于当前的组件,也就是传入 this;第二个参数是要找的组件的 name

findComponentUpward 方法会在 while 语句里不断向上覆盖当前的 parent 对象,通过判断组件(即 parent)的 name 与传入的 componentName 是否一致,直到直到最近的一个组件为止。

与 dispatch 不同的是,findComponentUpward 是直接拿到组件的实例,而非通过事件通知组件。比如下面的示例,有组件 A 和组件 B,A 是 B 的父组件,在 B 中获取和调用 A 中的数据和方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- component-a.vue -->
<template>
<div>
组件 A
<component-b></component-b>
</div>
</template>
<script>
import componentB from './component-b.vue';

export default {
name: 'componentA',
components: { componentB },
data() {
return {
name: 'Aresn'
}
},
methods: {
sayHello () {
console.log('Hello, Vue.js');
}
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- component-b.vue -->
<template>
<div>
组件 B
</div>
</template>
<script>
import { findComponentUpward } from '../utils/assist.js';

export default {
name: 'componentB',
mounted () {
const comA = findComponentUpward(this, 'componentA');

if (comA) {
console.log(comA.name); // Aresn
comA.sayHello(); // Hello, Vue.js
}
}
}
</script>

findComponentUpward 只会找到最近的一个组件实例,如果要找到全部符合要求的组件,就需要另外实现方法。

向上找到所有的指定组件——findComponentsUpward

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// assist.js
// 由一个组件,向上找到所有的指定组件
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 };
-------------本文结束感谢您的阅读-------------