React子组件间通过props进行通信

  在做基于React项目的时候,我们通常会将一个页面分割成多个可重用的组件以提高系统的可维护性,这其中常常出现子组件之间有通信的情况。举一个下订单例子:React子组件间通过props进行通信_第1张图片
React子组件间通过props进行通信_第2张图片
地址选择框展开样式如下:
React子组件间通过props进行通信_第3张图片
  这里简化处理:有一个订单页面(Order.tsx),它包含了两个子组件:地址选择组件(Area.tsx,有省市区三层选择)和邮编组件(Zipcode.tsx,邮编只精确到市,同一个市下面所有的区的邮编是一样的)。此时有一个需求:①当用户选择地址的时候要自动填充邮编;②当用户选择邮编时需要自动填充地址。
  我们可以知道Area和Zipcode这两个组件是独立的,它们之间只能通过Order这个父组件来实现信息交流。对于问题①是比较容易解决的:直接根据选择好的地址对应的邮编传给邮编组件即可。通过在父组件Order的state状态中定义一个邮编字段zipcode和一个更改邮编的函数handleChange(),然后子组件Area在选择地址时调用父组件的handleChange()函数来设置对应的邮编值,最后子组件Zipcode就可以通过this.state.zipcode来获得改变后的邮编,至此,问题①就可以解决了。如下图所示:
React子组件间通过props进行通信_第4张图片
  对于问题②,由于地址选择要精确到区,而邮编只到市的层级,所以当用户先选择邮编时,我们需要在地址组件处弹出所选邮编对应的省市下面对应的区供用户进一步选择精确的地址。如下:
React子组件间通过props进行通信_第5张图片
我们同样也需要在父组件Order的state状态中设置变量来使两个子组件进行通信。我们定义该字段为areaTrigger,Area中增加一个props属性areaTrigger来判断用户是否先选择了邮编,这里由于需要根据对应的省市地址弹出区地址选择框(需要执行一些函数),所以此时需要通过React的生命周期函数componentWillReceiveProps(nextProps){ }来监听地址的变化,该函数在组件的props属性发生变化时会触发。如下:React子组件间通过props进行通信_第6张图片
上图componentWillReceiveProps(nextProps){ }函数中的nextProps是最新的props属性,this.props是前一次props属性,通过对比着两个值是否相等就可以知道组件对应的props属性是否发生了变化。至此,我们决解了问题②了。

等等,我们真的解决了问题②了吗??
React子组件间通过props进行通信_第7张图片
  不知道你发现没有,其实还存在一个小问题:用户首次操作选择了一个邮编,此时地址栏可以正常弹出,然后关闭地址选择弹窗,再一次选择同样的邮编,此时就不会弹出地址弹窗了,如上图。为什么呢? 通过componentWillReceiveProps(nextProps){ }函数可以知道,我们是通过对比前后两次props属性值是否一样来判断是否需要弹窗,然而当连续选择同样的邮编时,只有第一次选择会弹出地址框,此后的选择都不会进入条件判断语句,因为选择同样邮编时areaTrigger的值并没有发生改变。 那么我们该怎么解决呢??这事好办,既然我们是通过对比前后两次的props值是否相同来决定是否弹出地址选择框,那么我们只需要在用户选择了邮编以后保证与前一次的props值不同不就可以了吗?如下图所示:React子组件间通过props进行通信_第8张图片
上图中,我们在原本设置的地址值的基础上末尾追加了一段字符串:FLAG + Math.random(),这样就基本可以保证用户连续选择同样的邮编时设置的地址值是不相同的,其中FLAG标志(可以随意设置,与目标字段内容不冲突即可)可以便于我们在componentWillReceiveProps(nextProps){ }函数中获取真正想要的地址。至此,我们想要的效果基本就达到了~

总结:
①我们可以通过以多个子组件的最近公共父组件作为中转站的方式来实现子组件间的通讯交流。
②使用componentWillReceiveProps(nextProps){ }函数对比前后props属性是否相同来触发某些行为时,我们可以在真正需要的值的后面附加一段变化的值来保证每次操作前后的值都不一样,从而可以使想要执行的函数每次都能触发。
最后,附上一张React生命周期图:React子组件间通过props进行通信_第9张图片


若对你有帮助,可以支持一下作者创作更多好文章哦~
赞赏码

你可能感兴趣的:(React)