《React+Redux前端开发实战》—2.3.4 非嵌套组件通信

举报
华章计算机 发表于 2019/07/24 23:42:06 2019/07/24
【摘要】 本节书摘来自华章计算机《React+Redux前端开发实战》一书中的第2章,第2.3.4节,作者是徐顺发.

2.3.4  非嵌套组件通信

  非嵌套组件就是没有包含关系的组件。这类组件的通信可以考虑通过事件的发布-订阅模式或者采用context来实现。

  如果采用context,就是利用组件的共同父组件的context对象进行通信。利用父级实现中转传递在这里不是一个好的方案,会增加子组件和父组件之间的耦合度,如果组件层次嵌套较深的话,不易找到父组件。

  那么发布-订阅模式是什么呢?发布-订阅模式又叫观察者模式。其实很简单,举个现实生活中的例子:

  很多人手机上都有微信公众号,读者所关注的公众号会不定期推送信息。

  这就是一个典型的发布-订阅模式。在这里,公众号就是发布者,而关注了公众号的微信用户就是订阅者。关注公众号后,一旦有新文章或广告发布,就会推送给订阅者。这是一种一对多的关系,多个观察者(关注公众号的微信用户)同时关注、监听一个主体对象(某个公众号),当主体对象发生变化时,所有依赖于它的对象都将被通知。

  发布-订阅模式有以下优点:

  •  耦合度低:发布者与订阅者互不干扰,它们能够相互独立地运行。这样就不用担心开发过程中这两部分的直接关系。

  •  易扩展:发布-订阅模式可以让系统在无论什么时候都可进行扩展。

  •  易测试:能轻易地找出发布者或订阅者是否会得到错误的信息。

  •  灵活性:只要共同遵守一份协议,不需要担心不同的组件是如何组合在一起的。

  React在非嵌套组件中只需要某一个组件负责发布,其他组件负责监听,就能进行数据通信了。下面通过代码来演示这种实现。

  非嵌套组件通信示例:

  (1)安装一个现成的events包:

  

  npm install events —save

  

  (2)新建一个公共文件events.js,引入events包,并向外提供一个事件对象,供通信时各个组件使用:

  

  import { EventEmitter } from "events";

  export default new EventEmitter();

  

  (3)组件App.js:

  

  import React, { Component } from 'react';

  import ComponentA from "./ComponentA";

  import ComponentB from "./ComponentA";

  import "./App.css";

  export default class App extends Component{

      render(){

          return(

              <div>

                  <ComponentA />

                  <ComponentB />

              </div>

          );

      }

  }

  

  (4)组件ComponentA:

  

  import React,{ Component } from "react";

  import emitter from "./events";

  export default class ComponentA extends Component{

      constructor(props) {

          super(props);

          this.state = {

              data: React,

          };

      }

      componentDidMount(){

          // 组件加载完成以后声明一个自定义事件

          // 绑定callMe事件,处理函数为addListener()的第2个参数

          this.eventEmitter = emitter.addListener("callMe",(data)=>{

              this.setState({

                  data

              })

          });

      }

      componentWillUnmount(){

          // 组件销毁前移除事件监听

          emitter.removeListener(this.eventEmitter);

      }

      render(){

          return(

              <div>

                  Hello,{ this.state.data }

              </div>

          );

      }

  }

  (5)组件ComponentB:

  

  import React,{ Component } from "react";

  import emitter from "./events";

  export default class ComponentB extends Component{

      render(){

          const cb = (data) => {

              return () => {

                  // 触发自定义事件

                  // 可传多个参数

                  emitter.emit("callMe", "World")

              }

          }

          return(

              <div>

                  <button onClick = { cb("Hey") }>点击</button>

              </div>

          );

      }

  }

  

  当在非嵌套组件B内单击按钮后,会触发emitter.emit(),并且将字符串参数World传给callMe。组件A展示的内容由Hello,React变为Hello,World。这就是一个典型的非嵌套组件的通信。

注意:组件之间的通信要保持简单、干净,如果遇到了非嵌套组件通信,这时候读者需要仔细审查代码设计是否合理。要尽量避免使用跨组件通信和非嵌套组件通信等这类情况。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。