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

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

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

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

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

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

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

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

<

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

React

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

画了一张粗劣的树形结构

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

  • 父子关系(子父关系),如:<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

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

这个也请轻喷。

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

  1. uniapp 子组件 props拿不到数据_来吧!一文彻底搞定Vue组件!

    点击蓝色 "达达前端小酒馆" 关注我哦! 加个 "星标" ,每天一篇文章,一起学编程 作者 |  Jeskson 来源 |  达达前端小酒馆 Vue组件的概述 ...

  2. uniapp 子组件 props拿不到数据_谈一谈使用 webpack 开发时,Vue 组件之间的数据传递...

    •我们在学习Vue的时候,难免会使用各个组件之间传递数据.•先来介绍一下Vue中组件传递的方式,有父组件传递给子组件数据,子组件传递给父组件数据,父组件直接获取子组件中数据,子组件直接获取父组件数据以 ...

  3. 前端React教程第三课 数据是如何在 React 组件之间流动

    04 数据是如何在 React 组件之间流动的?(上) 通过前面 3 个课时的学习,相信你已经对 React 生命周期相关的"Why""What"和" ...

  4. [react] 请说下react组件更新的机制是什么

    [react] 请说下react组件更新的机制是什么 靠事务批量更新 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, 但坚持一定很酷.欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

  5. uniapp 子组件 props拿不到数据_Vue组件间的几种通信方式

    前言 最近在刷面试题时,看见这个问题便做了个总结,欢迎各位补充!!! 为了更好的阅读性,请使用掘金访问 1.props & $emit--适用于父子组件通信 父组件通过prop向子组件传递数据 ...

  6. html 双向绑定组件,contenteditable联合v-html实现数据双向绑定的vue组件

    先看最终实现的demo效果图: (1)上面看似文本域的大框是通过给div添加contenteditable=true属性实现的Vue组件DivEditable.vue: (2)下面的输入框是父组件中与 ...

  7. elementui的tree组件页面显示不出数据_只要10分钟,教你配置出炫酷的数据可视化大屏...

    在电影<摩天营救>中,监控中心的全方位展示屏幕给人印象深刻.现在这种立体化大屏幕似乎成了好莱坞大片的标配.其实,这种逼格很高的镜头就是一个数据可视化大屏.随着社会信息化的高速增长,数据可视 ...

  8. ssis 角本组件更新数据_使用SSIS脚本组件作为数据源

    ssis 角本组件更新数据 介绍 (Introduction) SSIS Script component is one data transformation tasks in SQL Server ...

  9. 为啥我的页面模板的from提交不了数据_小程序,组件与模板对比,及其简单使用

    接着上篇 小程序,如果你会这两种方式,代码就简洁了,重复代码也少了,这篇来说说组件(component)和模板(template). 一.为啥要用组件呢? 正如上篇说的,为了页面简洁和代码的重复利用, ...

最新文章

  1. python拟合求参_机器学习作业(四)神经网络参数的拟合——Python(numpy)实现
  2. Android性能优化之提高ListView性能的技巧
  3. SVD理论以及Python实现
  4. Python编程基础:第四十二节 多重继承Multi Level Inheritance
  5. Java ConcurrentHashMap Example and Iterator--转
  6. Java基础篇:强制类型转换
  7. node --- 使用express.Router与body-parser
  8. JavaScript (If...Else和Switch和循环遍历) 语句以及常用消息框
  9. python 如何匹配一撇字符_python,yaml如何解析包含撇号的字符串
  10. 菜鸟学IT之python3关于列表,元组,字典,集合浅认识!
  11. Dapper的动态查询生成器
  12. c语言清空文件内容_C 语言清空输入缓冲区的几个手段
  13. WPF几个核心类的类层次结构
  14. mysql 升级和降级
  15. 三十七、【获取相机权限】
  16. C语言编程软件的选择和下载
  17. 疯狂的程序员 80-最后
  18. 如何让 uni-app 页面中的背景图片高度和宽度自适应
  19. 固态硬盘与机械硬盘的区别
  20. mysql数据库 auto_increment_mysql学习笔记(二:中的auto_increment 理解

热门文章

  1. Spring boot指定日志配置
  2. JSTL标签显示动态控件
  3. XML Schema简介
  4. mysql数据库雪崩_缓存与数据库一致性之三:缓存穿透、缓存雪崩、key重建方案...
  5. 分享一个获得Java项目经验的快速途径!
  6. Linux 服务器高并发调优实战
  7. 有关于Java Map,应该掌握的8个问题
  8. java11正式发布了,让java代码更完美
  9. solr异常--Expected mime type application/octet-stream but got text/html.
  10. tomcat运行报错Failed to start component [StandardEngine[Catalina].StandardHost[localhost].