博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
React的组件协同使用
阅读量:6458 次
发布时间:2019-06-23

本文共 6604 字,大约阅读时间需要 22 分钟。

  hot3.png

React将代码进行组件化,使得开发人员不用太过于关注UI层面的实现细节,考虑最多的也就是组件与组件之间的数据通信了。那么,在React开发中,有哪些场景的组件协同?又如何去实现组件的协同使用呢?

组件的协同本质上是对组件的一种组织、管理方式。

目的是使得系统 逻辑清晰、代码模块化、封装细节、代码可复用。

组件的协同分为两种方式:嵌套、抽离、发布订阅模式。

嵌套

组件嵌套的本质就是父子关系,即为父组件和子组件之间的通信。

总的来说有两种场景:

  • 父子组件通信
  • 兄弟组件通信

父子组件通信

首先我们先来看看最常用的一个手段,通过props属性。以父子组件为例,父组件只需要将数据以props的方式传递给子组件,子组件可以直接通过this.props来获取,比如:

// 父组件 Parentexport default class Parent extends React.Component {  constructor(props) {    super(props);    this.state = {      message: '传给子组件的消息'    }  }  // 消息回调  onMessage(messageFromChildren) {    console.log(messageFromChildren);  }  render() {    const { message } = this.state;    return (      
); }}
// 子组件 Childrenexport default class Children extends React.Component {  constructor(props) {    super(props);  }  handleClick() {    this.props.onMessage('来自子组件的消息');  }  render() {    const { message } = this.props;    return (      

{ message }

); }}

当然,如果Children子组件需要传递数据给到父组件,可以使用回调方式,父组件将方法的引用通过props传递给到子组件,如上代码中的handleClick里调用了onMessage。当父组件的state更新时,Children组件会重新渲染,使用最新的message数据。

bind的作用就是给函数增加默认的参数,第一个传参将替代方法里面的this

兄弟组件通信

兄弟组件不能直接相互通信,需要通过父组件来中转一下,进行状态提升。兄弟组件将需要共享的数据提升至共同的直接父组件中,然后就跟普通的父子组件通信一样了。比如:

// 父组件 Parentexport default class Parent extends React.Component {  constructor(props) {    super(props);    this.state = {      messageFromA: '',      messageFromB: ''    }  }  onMessage(messageFromChildren, from) {    console.log(messageFromChildren);    this.setState({      [from == 'A' ? 'messageFromA' : 'messageFromB']: messageFromChildren    });  }  render() {    const { messageFromA,  messageFromB} = this.state;    return (      
); }}
// 子组件ChildrenAexport default class ChildrenA extends React.Component {  constructor(props) {    super(props);  }  handleClick() {    this.props.onMessage('来自A子组件的消息', 'A');  }  render() {    const { message } = this.props;    return (      

{ message }

); }}
// 子组件 ChildrenBexport default class ChildrenB extends React.Component {  constructor(props) {    super(props);  }  handleClick() {    this.props.onMessage('来自B子组件的消息', 'B');  }  render() {    const { message } = this.props;    return (      

{ message }

); }}

当点击clickA的时候,子组件B接收到了子组件A的消息,反之亦然。

通过props的组件通信比较简单,但也有其自身的缺陷,当组件层级大于3层时,这种方式就不适合了,首先是深层级的传递对到维护来说简直就是噩梦,需要一层一层的看才能知道数据的来源及流向。其次的话,假如不止A、B子组件,还有C子组件的,A、B组件引发的父组件state更新会触发C子组件的更新,但事实上,C子组件并没有接收任何数据,容易造成资源浪费。

// Parent组件  render() {    const { messageFromA,  messageFromB} = this.state;    return (      
); }
// 子组件 ChildrenCexport default class ChildrenC extends React.Component {  constructor(props) {    super(props);  }  componentDidUpdate() {    console.log('ChildrenC updated');  }  render() {    return (      
ChildrenC
); }}

抽离

Mixin

这里要介绍的抽离主要是指Mixin。

假设有多个组件使用相同的getDefaultProps方法,我们就可以定义如下Mixin:

var DefaultNameMixin = {    getDefaultProps: function () {        return {name: "Tom"};    }};

Mixin相当于组件的一个扩展,它的本质就是一组方法的集合,使用这个 mixin 的组件能够自由的使用这些方法(就像在组件中定义的一样)。使用Mixin的目的就是横向抽离出组件的相似代码。

与Mixin思路相似的概念还有:AOP、插件等

例子中,DefaultNameMixin中包含getDefaultProps方法。除了直接定义外,Mixin还可以嵌套使用,也就是可以在定义Mixin时使用另一个Mixin:

var DefaultCommonMixin = {    mixins:[DefaultNameMixin], //use Mixin    getDefaultProps: function () {        return {food: "rice"};    }};

例子中,在DefaultCommonMixin的定义中嵌套使用了DefaultNameMixin,因此DefaultCommonMixin包含了DefaultNameMixin中定义的getDefaultProps方法,此时DefaultCommonMixin中有两个方法。使用Mixin时,只需将Mixin加入到mixins属性对应的数组中,Mixin的使用语法为mixins:[Mixin1,Mixin2……]。

使用Mixin时,只需将Mixin加入到mixins属性对应的数组中,Mixin的使用语法为mixins:[Mixin1,Mixin2……]。

var Component = React.createClass({    mixins:[DefaultCommonMixin], //use Mixin    render:function(){        return 

{this.props.name} like {this.props.food}

; }}); ReactDOM.render(
, document.getElementById("example"));

一个组件可以使用多个Mixin,同时,Mixin也可使用在多个组件中。

使用Mixin时,需要注意不要在多个地方设置相同的Prop和State。同时,在不同的Mixin中定义相同的方法,或者Mixin和组件中包含了相同的方法时,也会抛出异常,但是这种情况对componentDidMount等生命周期方法不适用(render方法除外,多次定义render方法也会抛出异常)。

如果在一个组件的多个地方定义了相同的生命周期方法,这些方法的执行顺序为:Mixin中的方法会优先执行(根据mixins中的顺序从左到右的顺序),然后执行组件中定义的方法。

Mixin的优点:

代码复用:抽离出通用代码,减少开发成本,提高开发效率

即插即用:可以直接使用许多现有的Mixin来编写自己的组件

适应性强:改动一次代码,影响多个组件

Mixin的缺点:

编写难度高:Mixin可能被用在各种环境中,兼容多种环境就需要更多的逻辑和代码,通用的代价是提高复杂度。

降低代码可读性:组件的优势在于将逻辑和界面直接结合在一起,Mixin本质上会分散逻辑,理解起来难度更大。

React的LinkedStateMixin

'use strict';    // 构建对象{value,requestChange},value为初始值,requestChange为方法,须手动调用  // 在本模块中,value为state[key]的初始值,requestChange用于更新state[key]  var ReactLink = require('./ReactLink');    // 设定属性key后,返回函数,该函数接受value,内部调用组件component.setState方法,更新state[key]=value  var ReactStateSetters = require('./ReactStateSetters');    /**  * 针对react手动调用setState方法的单向数据流,提供双向绑定  * 使用linkState(key).requestChange(value)传值后自动调用setState方法,更新state  *  * 示例  * var LinkedStateMixin = require('react-addons-linked-state-mixin');   * var WithoutLink = React.createClass({  *   mixins: [LinkedStateMixin],  *   getInitialState: function() {  *     return {message: 'Hello!'};  *   },  *   render: function() {  *     var valueLink = this.linkState('message');  *     var handleChange = function(e) {  *       valueLink.requestChange(e.target.value);  *     };  *     return ;  *   }  * });  */  var LinkedStateMixin = {    // ReactStateSetters.createStateKeySetter方法用于构建linkState(key)返回对象的requestChange方法    // 实现传值后自动调用setState方法,更新state    linkState: function (key) {      return new ReactLink(this.state[key], ReactStateSetters.createStateKeySetter(this, key));    }  };    module.exports = LinkedStateMixin;

使用上述的Mixin:

import LinkedStateMixin from 'react-addons-linked-state-mixin'mixins: [React.addons.LinkedStateMixin],

LinkedStateMixin仅仅是一个onChange/setState()模式的简单包装和约定。它不会从根本上改变数据在你的React应用中如何流动,也就是说其实LinkedStateMixin本质还是单向流,只是通过onChange将数据更改传递给React,然后内部数据改变就自动调用setState来进行更新。

使用示例:

var WithLink = React.createClass({  mixins: [LinkedStateMixin],  getInitialState: function() {    return {message: 'Hello!'};  },  render: function() {    return ;  }});

LinkedStateMixin给你的React组件添加一个叫做linkState()的方法。linkState()返回一个包含React state当前的值和用来改变它的回调函数的valueLink对象。

valueLink 对象可以在树中作为props被向上传递或者向下传递,所以它在组件层和状态层建立起双向绑定是非常简单的。

注意:

对于checkboxvalue属性,有一个特殊的行为,如果checkbox被选中(默认是on),value属性值将会在表单提交的时候发送出去。当checkbox被选中或者取消选中的时候,value属性是不会更新的。对于checkbox,你应该使用checkLink而不是valueLink

Reference:

1. http://schifred.iteye.com/blog/2361478

2. http://blog.csdn.net/qq_18661257/article/details/68951561

转载于:https://my.oschina.net/hosee/blog/1552825

你可能感兴趣的文章
Adb移植(一)简单分析
查看>>
Linux VNC server的安装及简单配置使用
查看>>
阿里宣布开源Weex ,亿级应用匠心打造跨平台移动开发工具
查看>>
Android项目——实现时间线程源码
查看>>
招商银行信用卡重要通知:消费提醒服务调整,300元以下消费不再逐笔发送短信...
查看>>
python全栈_002_Python3基础语法
查看>>
C#_delegate - 调用列表
查看>>
交换机二层接口access、trunk、hybird三种模式对VLAN的处理过程
查看>>
jQuery.extend 函数详解
查看>>
[转]Windows的批处理脚本
查看>>
lnmp高人笔记
查看>>
[转载] OpenCV2.4.3 CheatSheet学习(三)
查看>>
C#中跨窗体操作(2)--消息机制
查看>>
子程序框架
查看>>
多维数组元素的地址
查看>>
maven的错误记录
查看>>
数据库运维体系_SZMSD
查看>>
aspose 模板输出
查看>>
福大软工1816 · 第三次作业 - 结对项目1
查看>>
selenium多个窗口切换
查看>>