父子组件通信—Props传递数据和方法

父级组件将数据和方法以props形式传递给子组件供子组件使用

  1. import React,{ Component } from "react";
  2. import Sub from "./Sub.js";
  3. import "./App.css";
  4. export default class App extends Component{
  5. constructor(props){
  6. super(props)
  7. this.getCount = this.getCount.bind(this)
  8. }
  9. getCount(count){
  10. console.log(count);
  11. }
  12. render(){
  13. return(
  14. <div>
  15. <Sub title = "今年过节不收礼"
  16. getCount = { this.getCount }
  17. />
  18. </div>
  19. )
  20. }
  21. }
  1. import React,{ Component } from "react";
  2. class Sub extends Component{
  3. constructor(props){
  4. super(props)
  5. this.sendCount = this.sendCount.bind(this)
  6. }
  7. state = { count:0 }
  8. sendCount(){
  9. //调用父级组件传入的方法
  10. this.props.getCount(this.state.count)
  11. }
  12. return(
  13. const props = this.props
  14. <div>
  15. <h1> { props.title } </h1> //从父组件接受props信息展示
  16. <button onClick = { this.sendCount }>
  17. Click Me //将子组件信息传给父组件供使用
  18. </button>
  19. </div>
  20. )
  21. }
  22. export default Sub;

兄弟组件通信—状态提升

将数据和操作数据的方法,放在兄弟组件共同的父级组件上,也就是状态提升。

跨级组件通信—Context

跨级组件通信,就是父组件向子组件的子组件通信,向更深层的子组件通信。跨级组件通信可以采用下面两种方式:

  • 中间组件层层传递 props
  • 使用context对象

对于第一种方式,如果父组件结构较深,那么中间的每一层组件都要去传递 props,增加了复杂度,并且这些 props 并不是这些中间组件自己所需要的。
使用 context 是另一种可行的方式,context 相当于一个全局变量,是一个大容器,我们可以把要通信的内容放在这个容器中,这样一来,不管嵌套有多深,都可以随意取用。

  1. import React,{ Component } from "react";
  2. import Sub from "./Sub.js";
  3. import "./App.css";
  4. export default class App extends Component{
  5. constructor(props){
  6. super(props)
  7. this.getCount = this.getCount.bind(this)
  8. }
  9. // 上级组件声明自己支持 context
  10. static childContextTypes = {
  11. color:PropTypes.string,
  12. getCount:PropTypes.func,
  13. }
  14. // 父组件提供一个函数,用来返回相应的 context 对象
  15. getChildContext(){
  16. return{
  17. color:"red",
  18. getCount:this.getCount.bind(this)
  19. }
  20. }
  21. getCount(count){
  22. console.log(count);
  23. }
  24. render(){
  25. return(
  26. <div>
  27. <Sub title = "今年过节不收礼"
  28. getCount = { this.getCount }
  29. />
  30. </div>
  31. )
  32. }
  33. }
  1. import React,{ Component } from "react";
  2. class Sub extends Component{
  3. constructor(props){
  4. super(props)
  5. this.sendCount = this.sendCount.bind(this)
  6. }
  7. // 下级组件声明自己需要使用context 不接收就获取不到context对象
  8. static contextTypes = {
  9. color:PropTypes.string,
  10. getCount:PropTypes.func,
  11. }
  12. state = { count:0 }
  13. sendCount(){
  14. //使用context使用接受到的方法
  15. this.context.getCount(this.state.count);
  16. }
  17. return(
  18. const props = this.props
  19. <div>
  20. <h1> { props.title } </h1> //从上级组件接受props信息展示
  21. <button onClick = { this.sendCount }>
  22. Click Me //将下级组件信息传给父组件供使用
  23. </button>
  24. </div>
  25. )
  26. }
  27. export default Sub;

任意组件间通信—PubSub

没有任何包含关系的组件,包括兄弟组件以及不在同一个父级中的非兄弟组件。对于非嵌套组件,可以采用下面两种方式:

  • 利用二者共同父组件的 context 对象进行通信
  • 使用消息订阅发布机制进行通信

首先,需要在项目引入PubSub库

  1. npm install pubsub-js --save

其次,需要在组件中引入PubSub,并做好消息订阅与发布

  1. import React, { Component } from 'react'
  2. import PubSub from 'pubsub-js'
  3. class Publish extends Component{
  4. constructor(props){
  5. super(props)
  6. this.sendCount = this.sendCount.bind(this)
  7. }
  8. state = { count:0 }
  9. sendCount(){
  10. //发布消息
  11. PubSub.publish('sendCount',{isLoading:false,users:response.data.items})
  12. }
  13. return(
  14. const props = this.props
  15. <div>
  16. <h1> { state.xxxx } </h1>
  17. <button onClick = { this.sendCount }>
  18. Click Me //发布消息
  19. </button>
  20. </div>
  21. )
  22. }
  23. export default Publish;
  1. import React, { Component } from 'react'
  2. import PubSub from 'pubsub-js'
  3. class Subscribe extends Component{
  4. constructor(props){
  5. super(props)
  6. state = { count:0 }
  7. this.setCount = this.setCount.bind(this)
  8. }
  9. setCount(){}
  10. componentDidMount(){
  11. //订阅消息
  12. this.token = PubSub.subscribe('sendCount',(_,stateObj)=>{
  13. //回调函数接收两个参数,消息名&&消息内容
  14. //必须使用箭头函数或者正确bind this的函数this.setCount
  15. this.setState(stateObj)
  16. })
  17. }
  18. componentWillUnmount(){
  19. //组件取消挂载时,取消订阅
  20. PubSub.unsubscribe(this.token);
  21. }
  22. return(
  23. const props = this.props
  24. <div>
  25. <h1> { state.count } </h1>
  26. </div>
  27. )
  28. }
  29. export default Subscribe;

任意组件间通信—集中式状态管理

React中数据通信是单向的,即父组件可以通过props向子组件传递数据,而子组件却不能向父组件传递数据。要实现子组件向父组件传递数据的需求,需要父组件提供一个修改数据的方法,当页面越来越多的时候,数据的管理就会变得异常复杂。
Redux是由Dan Abramov开源的一款前端状态管理框架,Redux将状态管理分为Action、Store和Reducers三部分。其中,Redux将应用程序的状态存储到Store中,组件通过dispatch()方法触发Action,Store接收Action并将Action转发给Reducer,Reducer根据Action类型对状态数据进行处理并将处理结果返回给Store,其他组件通过订阅Store状态的来刷新自身的状态。
如图所示,即为React原理
redux原理图.png

参考

  1. https://www.jianshu.com/p/fb915d9c99c4 React组件间通信的几种方式
  2. https://zhuanlan.zhihu.com/p/89015701 React使用PubSub实现消息订阅发布
  3. https://github.com/mroderick/PubSubJS PubSub Github仓库地址
  4. https://www.cxyzjd.com/article/sinat_17775997/82692621 PubSub回调函数bind this
  5. https://cloud.tencent.com/developer/article/1817831
  6. https://juejin.cn/post/7031509723190919175 Redux集中式状态管理
  7. https://segmentfault.com/a/1190000039419540 Redux实践1