![React.js实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/858/26542858/b_26542858.jpg)
3.2 组件之间的通信
在React进行项目开发中,难免会进行组件之间的信息传递操作,即组件间的通信。通信可以简单地理解为组件之间的数据传递,如父子组件之间的通信、同级组件之间的通信等。
在学习组件通信之前,读者应该先对React中的state和props有所掌握。state和props是React中的两种数据方式,无论是state数据还是props数据只要发生数据改变,就会重新渲染组件。那么本节就来讲述state和props的使用方法。
3.2.1 props
props是properties的简称,范围为属性。在React中的组件都是相对独立的,一个组件可以定义接收外界的props,在某种意义上就可以理解为组件定义了一个对外的接口。组件自身相当于一个函数,props可以作为一个参数传入,旨在将任意类型的数据传给组件。
props的使用方法如示例3-1所示。
【示例3-1 props简单使用】
![](https://epubservercos.yuewen.com/074AAD/15056704604178706/epubprivate/OEBPS/Images/Figure-P44_1.jpg?sign=1738852978-heplnsgdV1Gt94y1DV9maFI1oudepl57-0-4af9f58a3c521e58cac381a01850102f)
在上面的例子中,先定义一个名为SayName的组件(注意:在React中定义组件一定要用大驼峰法,首字母要大写),在render()中返回一个<h1>的DOM节点,整体渲染<SayName>这个组件的时候,用this.props.name来获取name属性。当然props也可以在挂载组件的时候为其设置初始值,如示例3-2所示。
【示例3-2 初始化props】
![](https://epubservercos.yuewen.com/074AAD/15056704604178706/epubprivate/OEBPS/Images/Figure-P45_1.jpg?sign=1738852978-pvvRiIMpnnfKOaHIQ15AaHy83ai2WTm2-0-acba3e015fcd859d3640bc00f79784be)
props一般不允许更改,所以这里用static关键字来定义默认的props值。在ES5中初始化props使用getDefaultProps()方法来实现,在ES6中统一使用static类型来定义。
提示
props的属性值不允许组件自己修改,如果需要修改props值,请使用state(后面会介绍)
3.2.2 state
state为状态之意。组件在React中可以理解为是一个状态机,组件的状态就是用state来记录的。相对props来说,state是用在组件内部并且是可以修改的。
在state的操作中,基本操作包括初始化、读取和更新。下面通过一个示例来介绍state的基本操作,实现改变DOM元素颜色。
【示例3-3 利用state改变DOM元素颜色】
![](https://epubservercos.yuewen.com/074AAD/15056704604178706/epubprivate/OEBPS/Images/Figure-P46_1.jpg?sign=1738852978-N4Dm6USiLLCzC93MFuAGVSkozlYPyvOt-0-74e5d71ee2e03115cc3dc520df0517d1)
在上面的例子中,state的初始化放在constructor的构造函数中,该例子中isRed就是一个组件的state,初始化为true。接下来在组件渲染中,即调用rend函数时,<h1>中的this.state.isRed值为true,则style为redStyle,即红色。在<button>中绑定handleClick方法,利用setState来改变state中的isRed值。setState方法有两个参数,官方给出的说明如下:
![](https://epubservercos.yuewen.com/074AAD/15056704604178706/epubprivate/OEBPS/Images/Figure-P47_2.jpg?sign=1738852978-nTFm8MkbcK8kkWCL1dMp3Rrw3zz52sBf-0-deca80fbe0a9c79bdbf4cc9544d0bc18)
第一个参数表示的是要改变的state对象,第二个参数是一个回调函数,这个回调函数是在setState的异步操作执行完成并且组件已经渲染后执行的。所以,可以通过该方法获取之前的状态值prevState。该示例就是通过setState获取之前的状态值prevState,对其进行更新操作,从而重新渲染组件。
3.2.3 父子组件通信
在介绍组件通信之前,先引入一个概念:数据流。在React中,数据流是单向的,通过props从父节点传递到子节点,如果父节点的props发生改变,则React会遍历整棵组件树,从而渲染用到这个props的所有组件。
父组件更新子组件,可以直接通过props进行信息传递,实现更新操作,如示例3-4所示。
【示例3-4 子父组件通信】
![](https://epubservercos.yuewen.com/074AAD/15056704604178706/epubprivate/OEBPS/Images/Figure-P47_3.jpg?sign=1738852978-o1S0HXEzcNYhVKF4f2DtXnFPTZhWl1cK-0-d1e2d553ee5165eef5fb1bd0d461990f)
在父组件<Father />中,dom节点<button>绑定refreshChild()方法,在refreshChild()方法中直接修改state值,传给子组件即可。
子组件更新父组件,需要父组件传一个回调函数给子组件,然后子组件调用,就可以触发父组件更新了,如示例3-5所示。
【示例3-5 父子组件通信】
![](https://epubservercos.yuewen.com/074AAD/15056704604178706/epubprivate/OEBPS/Images/Figure-P49_1.jpg?sign=1738852978-qinQgX5gWK5kYSkDj2KK3zShtnrB8tPb-0-8a8059d903f7a69e2b5b8832a21f2290)
子组件<Child />调用父组件的refreshParent()方法,触发后修改state值,从而更新父组件内容。
3.2.4 同级组件通信
所谓同级组件,即组件们有一个共同的祖先,但其各自的辈分一样。同级组件之间的通信有两种方式:
·第一种:组件与组件之间有一个共同的父组件,可以通过父组件来通信,即一个子组件可以通过父组件的回调函数来改变props,从而改变另一个子组件的props。
·第二种:组件与组件之间有共同的祖先,但不一定是亲兄弟,这样如果通过父组件一级一级去调用,效率会很差。React提供了一种上下文方式,允许子组件可以直接访问祖先组件的属性和方法,从而使效率得到很大的提升。
兄弟组件通信,如示例3-6所示。
【示例3-6 兄弟组件通信】
![](https://epubservercos.yuewen.com/074AAD/15056704604178706/epubprivate/OEBPS/Images/Figure-P50_2.jpg?sign=1738852978-SsE8jSgCFTJv95TnNfoQoEQ397qGT0n7-0-f57888c766b53dd3cf32c24ed6fe4f6b)
![](https://epubservercos.yuewen.com/074AAD/15056704604178706/epubprivate/OEBPS/Images/Figure-P51_1.jpg?sign=1738852978-ypJ4Dtp1dPxhVqt827jjvyLo9l18rN0Z-0-b03af80d6bca6988444c4640d4b11a42)
![](https://epubservercos.yuewen.com/074AAD/15056704604178706/epubprivate/OEBPS/Images/Figure-P52_1.jpg?sign=1738852978-HBZVPQgIZBi84fXAQJOlIWLRUn36tpHe-0-44e0160629b247def619e0bb661b5708)
<Brother1/>和<Brother2/>是两个兄弟组件,二者有一个共同的父组件,第一个子组件<Brother1/>可以通过父组件<Father/>的回调方法修改state,当父组件的state有了改动之后,其改动的state会传给其所有子组件后重新渲染,这样就达到了兄弟节点之间的通信。