uniapp 子组件 props拿不到数据_总结下React组件间的通讯

853eb1c215f4ff70ea9bf58711e56dd3.png
这是个老话题了。
随着组件化开发成为主流,每个组件都有完善的生命周期,大家可以在生命周期内做一些事情,每个组件有自己的状态管理机制。同时,每个组件都是独立的。这能提高大家的开发效率,规范化开发。

今天,想整理下每个独立组件间如何通讯呢?这很关键,关键到每次开发中都会遇到,习以为常了。

我想我可以根据下面4点进入话题。

  1. 组件间可能存在哪些形式关系呢?他们有哪些通讯需求呢?
  2. 常用的通讯'手段'方式有哪些呢?
  3. 适用的场景呢?组件间特定的某种关系下,用那种通讯方式更好呢?
  4. 扩展一下

如果,你看到了这篇文章。那么,能有你的反馈就更棒了。

一:组件间存在哪些关系形式呢?

我们知道,在标准网页中,组织页面文档的对象被组织在一个树形结构。

同样,在React中,各个组件也是被组织在一个树形结构中。平时写惯了JSX,不会在意这种关系,JSX 最终的会被编译成React.createElement( type, [props], [...children] ),更能明显的发现这种关系。比如:

<

会被编译为以下(这也是,为什么即便我们写React函数式组件,也需要引入React,不然会报import ‘react’错误的原因

React

所以,React组件间存在的关系呢,可以想象以下一个树形结构各个节点存在的关系。

ca55ba81fc6554bb0e10850f9620a622.png
画了一张粗劣的树形结构

组件间大概存在的关系是:

  • 父子关系(子父关系),如:<Root>与<ParentA>
  • 兄弟关系,如:<ParentA>与<ParentB>
  • '没有'关系(因为隔了太多级,忽略为没有关系),如<ParentA>与<Son1_1>,<ChildA1>与<ChildB1>

然后组件有哪些通讯需求呢?

  • 父组件向子组件通讯
  • 子组件向父组件通讯
  • 兄弟组件间的通讯
  • 没有关系的组件间的通讯,比如‘群发’

现在我们分析存在的通讯需求,下面我们先来看看有哪些通讯'手段'方式。

二:常用的通讯'手段'方式有哪些呢?

a.通过props传递参数,进行通讯

在react中,数据流是单向流动 (自上层往下层流动) 的,数据通过props从父组件传递到子组件,子组件可以通过props获取父组件传递过来的数据。

上面我们提到每个组件都有独立的声明周期、状态管理。我们可以利用这些特色,完成父组件子组件的通讯。当父组件需要通知子组件时,通过setState触发状态变化,传递props,完成通讯。下面展示的是单级的情况,多级的情况是一样的,在Child中引入其他组件,给它传递props,参数很多的情况,可以利用ES6的...运算符进行结构,如:{...this.props},代码如下:

class 

b.通过调用props传递function,进行通讯

如果子组件需要向父组件通讯呢?我们知道props可以传递多种数据类型(number、bool、object、string、func等)。

因此,父组件可以通过props给子组件传递func类型的参数,子组件内通过调用这个func类型的参数,完成通讯,代码如下:

class 

c.通过ref获取组件实例,调用实例方法进行通讯

注:React推崇的是通过数据流,来完成组件间的通讯,更多情况下,我们都可以通过props数据完成需求。这里只是提供一种思路,大家不要滥用

如果我们能获取到一个组件的实例,那就意味着我们可以调用这个实例内的方法,完成组件间通讯。React给我们提供获取组件实例的方法ref。

这种方式适用于哪些使用场景?

我想可以举1、Toast类型的组件中的应用;2、高阶组件中的应用

都在项目中都用过Toast这种类型的组件,这种组件的特点是:

  • 用得非常频繁,可能多次调用。
  • 在各种不同的组件上都有可能用到
  • 需求比较稳定,稳定到我们可以预知(成功、失败、提醒、信息)

因为调用频繁,从性能方面考虑,我们需要它只创建一次,不要重复的创建。

因为在不同组件内用到,所以我们希望不用在不同的组件内进行写入组件,可以用最简单的方式调用。结合需求,我们希望用这样的形式调用。比如这样:Toast.success('成功了');、Toast.error('失败了');、Toast.tip('登录超时了');

如果,让你做个Toast组件你会怎么做呢?

我是通过ref获取Toast组件实例,通过实例操作Toast组件内的信息队列,来实现。一下是github源码地址,有兴趣的可以了解下。当然也有其他方式。欢迎大家评论(请轻喷)哈。

Toast组件演示,有代码注释。

以下代码简单演示下通过ref通讯

class 

以下是高阶组件中的应用。

大家都用过类似“onClickOutside”这样的高阶组件。高阶组件,由于通用性较高,因此,往往需要在高阶组件内直接调用WappedComponent内部的方法,因此,需要通过用ref获取WappedComponent组件实例,在通过实例调用内部的方法。

案例的话可以去git上看下onClickOutside的源码。

d.通过回调函数方法进行通讯

在b方案中,我们知道可以通过子组件调用props传递的方法完成通讯。

在此基础上,我们引入一个需求,需要在父组件的方法被调用后,告诉子组件调用完成。来完成Child ->Parent->Child这样的通讯。

当然我们可以通过结合a、b两种方案来完成需求,在Parent组件中存储一个状态,代表Child组件完成了调用。

但是,有时候,我们不希望在Parent组件中维护这样的一个状态,这个时候我们就可以通过回调方法的方式完成这种需求。提供我写的一个panel组件的一个案例,在窗口关闭前,需要让父组件完成退出动画,在退出动画完成后,在通知panel组件可以隐藏关闭按钮,而后关闭了。欢迎大家评论(请轻喷)哈。github地址:

一个动画面板组件,用了回调方法

以下代码简单演示下通过回调函数方法进行通讯

class 

e.观察者模式,添加订阅,发布通知的方式进行通讯

假设两个组件间'没有关系',如果我们想通过props进行通讯,那么会造成两个问题

  • 参数需要跨多层级的传递
  • 数据需要走到共同的父组件,完成setState状态更新,再创给子组件。会造成共同的组件逻辑会混乱,setState后,所有的子组件都会'更新',造成浪费(虽然你可以用PureComponent、或者shouldComponentUpdate优化不必要的性能浪费)

这个时候,我们可以考虑封装一个简洁的观察者模式(订阅与通知)。通讯目标组件添加通知订阅,在通讯源组件调用通知。

这样通知的时候只会更新添加了对应订阅的组件,其他组件不会影响。不同的组件也可以添加同一个订阅,完成所谓的群发。

github地址,大家可以参考下。

一个简单的观察者模式,代码有注释

以下用代码简单展示下,具体代码可以看github地址:

// 简易的观察者模式

f.引入Redux等

在业务比较复杂的代码中大家可以引入Redux来管理我们的数据,Redux分两部分redux和react-redux。

react-redux相对好理解一些,提供Provider和Connect两个高阶组件。Provider确保Children.only;Connect 实现stateToProps、dispatchToProps,同时在componentDidMount时添加订阅,在componentWillUnmout时移除订阅。

而,redux提供非常经典。提供了reducer、dispatch、subscribe、applyMiddleware的整条方案。这部分要深入的话可以写很多,有机会再写一篇来深入讲讲源码。

三:扩展

到这里也差不多了。

大概分享了下组件间的关系。

  • 父子关系(子父关系),如:<Root>与<ParentA>
  • 兄弟关系,如:<ParentA>与<ParentB>
  • '没有'关系(因为隔了太多级,忽略为没有关系)

组件间的通讯方式。

  • 通过props传递参数,进行通讯
  • 通过调用props传递function,进行通讯
  • 通过ref获取组件实例,调用实例方法进行通讯
  • 通过回调函数方法进行通讯
  • 观察者模式,添加订阅,发布通知的方式进行通讯
  • 引入Redux等

同时,如果可以用props数据流的方式实现的尽量用props数据流的方式进行。展示了一些代码,然后一个组件库,会慢慢完善,出一套对应的移动版,还没有发布npm。

一些React组件​coocssweb.github.io

如果能有你的反馈那就太好了。如果能有你的反馈那就太好了。

如果,大家有其他的方式,可以评论。或者这些方式有哪些不合理,也可以轻喷。

One More Thing

嗯哼?封面是手画的,就那很丑的那张,我画的。

这个也请轻喷。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值