跳到主要内容

vue、react 多层级组件通讯方式

· 阅读需 6 分钟

vue

1.父子组件通讯

一般都是子组件定义prop然后父组件传递prop参数

子组件通过 $emit 触发事件,通知父组件。父组件通过 $on或者html上通过@+事件名来监听组件的事件

2.兄弟组件通讯 (eventbus)

简单版使用event Bus的方式,即new 一个Vue,通过这个实例触发$emit以及监听$on来实现。

3.多层级的组件通讯 (this.$parent, this.$children)

一般情况下使用上面的方式是没有多大问题的,但是如果业务复杂了,有时会出现多层级的组件通讯,比如 A -> B -> C... 这种方式如果还是继续用父子组件通讯的一般方式,将要不断写prop,并且要不断的传递下去。对项目来说,这是非常难以维护的,因为很可能会改了一些业务代码导致没有传递prop出现报错情况。当然直接使用vuex是不会有这个问题。

可是今天看了下iview框架的组件源码,我发现他们组件通讯的变通方式

iview是一个基于vue的ui框架,有很多丰富的组件。组件之间存在各种嵌套。所以少不了组件的通讯,可是组件的使用是看业务的,他们的关系不一定会是父子的关系

来看看iview是如何处理组件的通讯

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));
}
}

这个是iview的组件的mixins 这部分的代码意思就是传入一个组件名称,事件名,以及参数,然后通过$parent不断的往上找到这个名称的组件,直到$root也就是根节点。找到父组件后,由父组件来触发$emit事件,原来的事件以及参数也原样推上去。

解决了什么问题?

如果存在很多层级的组件关系,很远层级的子组件触发了一个事件,这个时候最上层的父组件需要知道这些事件的发生,来处理一些东西,使用prop这种方式就变得很可怕,而且这种方式绑住了他们的关系。因为类似这种ui框架,组件是随处可用的。使用上面的代码,通过mixins方式引入到组件里面,当遇到这个情况的时候,就调用这个方法,随便选择这个组件的上级父组件,触发事件。非常友好的解决了多层级组件通讯的问题,也不用引入event Bus或者vuex这些解决方案,引入这些反而会导致组件不好使用了。

4.vuex全局状态管理

5. provide、inject

6. 路由组件传参,在路由上定义的prop参数

7.localStorage前端缓存,组件加载时可以获取数据,也是一个通信方式

8.作用域插槽

React

react 的组件通讯方式,不像vue那样要定义个prop然后再传递啥东西。

1.父子组件通讯

直接在父组件写传递的字段,子组件通过props来直接使用父组传过来的参数,当然这个props也是可以在子组件定义好类型的,这些不再讨论的范围内。

子组件想要跟父组件通讯也很简单,直接通过this.props调用父组件的函数就可以了,前提是父组件需要上定义好这个事件名。

2.兄弟组件的通讯

从网上搜索到结果是一个组件直接修改父组件的props的值,然后父组件的props传递给另一个子组件的参数就会发生改变,其实就是把父组件变成了桥接。

3.多层级的组件通讯

也是网上搜到的解决方案是,顶层父组件设置context,子组件接受这个context的方式,(官网文档有写这个部分的实现)。就算这里面有很多个组件的层级都不需要每层都传递了props了

当然也是可以通过redux这些方案的