![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=1738845508-LHCHFsVm6exArDXKLavMzHSJ4zsXsDpu-0-2ce5c9d5e35e5fae5d46c16ef6824737)
在上面的例子中,先定义一个名为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=1738845508-GrWlsagJjAI3Ej4fBqrwMuPUu4nGS6JV-0-59b9a95aec08014f9324a883d8b6d845)
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=1738845508-C0HxxixSSbkhh4nhZLKQTcxdAAnAQngA-0-90e6aadcbbfae163f8b7f8e2fbfc4ac6)
在上面的例子中,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=1738845508-UcK234kQ6ema5mPr4oDmYtxhsewjORjb-0-5719a22cc4e72b85e727f2841d169caf)
第一个参数表示的是要改变的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=1738845508-ivs0ZdhMp4JSEmueikZalI0qALEfRC5r-0-62e1919c0b6f3b89d29e15e215df9116)
在父组件<Father />中,dom节点<button>绑定refreshChild()方法,在refreshChild()方法中直接修改state值,传给子组件即可。
子组件更新父组件,需要父组件传一个回调函数给子组件,然后子组件调用,就可以触发父组件更新了,如示例3-5所示。
【示例3-5 父子组件通信】
![](https://epubservercos.yuewen.com/074AAD/15056704604178706/epubprivate/OEBPS/Images/Figure-P49_1.jpg?sign=1738845508-rsDV1vzFjjEqBIffOr81EZYTmUscEhh9-0-b910ce7f485d628c66d88f154d23a919)
子组件<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=1738845508-fJLZ07oIP4kwxQ9KvxzRY7Er6FKeYF3g-0-9f43aa72974e35dd0ad76af25a2d7099)
![](https://epubservercos.yuewen.com/074AAD/15056704604178706/epubprivate/OEBPS/Images/Figure-P51_1.jpg?sign=1738845508-yTmMbKnB5L8a4rwanpDCNF8Bh1LP6T6C-0-ac8166ad2e0be9d01733da0b6218fb16)
![](https://epubservercos.yuewen.com/074AAD/15056704604178706/epubprivate/OEBPS/Images/Figure-P52_1.jpg?sign=1738845508-eJupMEp58IAiNq9xXAz94GuCxcmzyyuX-0-8b0bb0176668bfd803f4b8a10b197ae4)
<Brother1/>和<Brother2/>是两个兄弟组件,二者有一个共同的父组件,第一个子组件<Brother1/>可以通过父组件<Father/>的回调方法修改state,当父组件的state有了改动之后,其改动的state会传给其所有子组件后重新渲染,这样就达到了兄弟节点之间的通信。