• React 数据通信总结(父子组件、跨级组件、无关组件)


    目录

    父子组件之间通信

    父组件向子组件传递数据和方法

    父组件获取子组件数据和方法

    跨级组件之间通信

    使用props实现跨级组件通信

    使用context实现跨级组件通信

    使用状态管理实现跨级组件通信

    无关组件之间通信

    使用EventEmitter实现无关组件之间通信

     使用状态管理实现无关组件通信

    补充:自己实现一个EventEmitter


    父子组件之间通信

    父组件向子组件传递数据和方法

    父组件可以向子组件传递数据和方法,子组件通过props来获取。

    父组件:

    1. import React from "react";
    2. import Child from "./Child";
    3. export default class Demo extends React.Component {
    4. constructor(props) {
    5. super(props)
    6. this.state = {
    7. value: 0
    8. }
    9. this.changeValue = this.changeValue.bind(this)
    10. }
    11. changeValue() {
    12. this.setState({
    13. value: this.state.value + 1
    14. }, () => {
    15. console.log('changeValue 方法执行了 value: ', this.state.value)
    16. })
    17. }
    18. render() {
    19. const value = this.state.value
    20. return (
    21. <div>
    22. <h1>父组件h1>
    23. <p>value: {value}p>
    24. <Child
    25. // 向子组件传递数据
    26. value={value}
    27. // 向子组件传递方法
    28. changeValue={this.changeValue}
    29. >Child>
    30. div>
    31. )
    32. }
    33. }

    子组件:

    1. import React from "react";
    2. export default class Child extends React.Component {
    3. constructor(props) {
    4. super(props)
    5. }
    6. dealClidk() {
    7. // 子组件触发父组件的方法执行
    8. this.props.changeValue()
    9. }
    10. render() {
    11. return (
    12. <div>
    13. <h1>子组件h1>
    14. {/* 子组件通过props获取父组件传递的数据 */}
    15. <p>value:{this.props.value}p>
    16. <button onClick={this.dealClidk.bind(this)}>点击button>
    17. div>
    18. )
    19. }
    20. }

     

    当点击子组件中的按钮时,就可以通过触发父组件的方法而改变父组件中的属性值。 

    父组件获取子组件数据和方法

    父组件可以通过ref获取子组件的数据和方法。

    父组件:

    1. import React from "react";
    2. import Child from "./Child";
    3. export default class Demo extends React.Component {
    4. constructor(props) {
    5. super(props)
    6. this.ChildRef = React.createRef()
    7. }
    8. dealClidk() {
    9. if (this.ChildRef && this.ChildRef.current) {
    10. // 父组件触发子组件方法的执行
    11. this.ChildRef.current.changeValue()
    12. }
    13. }
    14. getData() {
    15. if (this.ChildRef && this.ChildRef.current) {
    16. // 父组件获取子组件中state的值
    17. const childData = this.ChildRef.current.state.data
    18. console.log('获取子组件的数据 childData: ', childData)
    19. }
    20. }
    21. render() {
    22. return (
    23. <div>
    24. <h1>父组件h1>
    25. <button onClick={this.dealClidk.bind(this)}>点击button>
    26. <button onClick={this.getData.bind(this)}>获取button>
    27. <Child ref={this.ChildRef}>Child>
    28. div>
    29. )
    30. }
    31. }

    子组件:

    1. import React from "react";
    2. export default class Child extends React.Component {
    3. constructor(props) {
    4. super(props)
    5. this.state = {
    6. data: 0
    7. }
    8. this.changeValue = this.changeValue.bind(this)
    9. }
    10. changeValue() {
    11. this.setState({
    12. data: this.state.data + 1
    13. }, () => {
    14. console.log('changeValue 方法执行了 data: ', this.state.data)
    15. })
    16. }
    17. render() {
    18. const data = this.state.data
    19. return (
    20. 子组件

    21. value:{data}

  • )
  • }
  • }
  •  

    跨级组件之间通信

    使用props实现跨级组件通信

    使用props实现跨级组件通信也有两种方法。

    直接一级一级的传递

    父组件: 

    1. import React from "react";
    2. import Child from "./Child";
    3. export default class Demo extends React.Component {
    4. constructor(props) {
    5. super(props)
    6. this.state = {
    7. value: 0,
    8. value2: '张三'
    9. }
    10. this.changeValue = this.changeValue.bind(this)
    11. }
    12. changeValue() {
    13. this.setState({
    14. value: this.state.value + 1
    15. }, () => {
    16. console.log('changeValue 方法执行了 value: ', this.state.value)
    17. })
    18. }
    19. render() {
    20. const { value, value2 } = this.state
    21. return (
    22. <div>
    23. <h1>父组件h1>
    24. <p>value: {value}p>
    25. <p>value2: {value2}p>
    26. <button onClick={this.changeValue}>点击button>
    27. <Child
    28. value={value}
    29. value2={value2}
    30. >Child>
    31. div>
    32. )
    33. }
    34. }

     子组件:

    1. import React from "react";
    2. import GrandSon from "./GrandSon";
    3. export default class Child extends React.Component {
    4. render() {
    5. const { value, value2 } = this.props
    6. return (
    7. <div>
    8. <h1>子组件h1>
    9. <GrandSon
    10. // 子组件将数据继续向下传递
    11. value={value}
    12. value2={value2}
    13. >GrandSon>
    14. div>
    15. )
    16. }
    17. }

    孙子组件

    1. import React from "react";
    2. export default class GrandSon extends React.Component {
    3. constructor(props) {
    4. super(props)
    5. }
    6. render() {
    7. const { value, value2 } = this.props
    8. return (
    9. <div>
    10. <h1>孙子组件h1>
    11. <p>value: {value}p>
    12. <p>value2: {value2}p>
    13. div>
    14. )
    15. }
    16. }

    这种方式适合传递的数据比较少的情况,可以一个一个传递,如果传递的数据比较多的话使用这种方式传递就容易造成代码重复。我们可以使用{...this.props}的方式打包传递。不管父组件传递了多少数据,子组件都打包将所有数据传递给孙子组件,孙子组件依然使用this.props获取即可。

    我们修改下子组件的传递方式;

    1. import React from "react";
    2. import GrandSon from "./GrandSon";
    3. export default class Child extends React.Component {
    4. render() {
    5. return (
    6. 子组件

    7. <GrandSon
    8. // 子组件将数据继续向下传递
    9. {...this.props}
    10. >GrandSon>
  • )
  • }
  • }
  •  

    可以看到实现了相同的效果。

    使用context实现跨级组件通信

    使用context实现跨级传递数据,需要以下几步:

    1、通过React.createContext()创建一个context实例

    1. import React from "react";
    2. const DemoContext = React.createContext()
    3. export default DemoContext;

    2、通过provider创建一个生产者,provider有一个value属性可以用来包装所需要传递的数据

    1. import React from "react";
    2. import Child from "./Child";
    3. import DemoContext from './DemoContext'
    4. export default class Demo extends React.Component {
    5. constructor(props) {
    6. super(props)
    7. this.state = {
    8. value: 0,
    9. value2: '张三'
    10. }
    11. this.changeValue = this.changeValue.bind(this)
    12. }
    13. changeValue() {
    14. this.setState({
    15. value: this.state.value + 1
    16. }, () => {
    17. console.log('changeValue 方法执行了 value: ', this.state.value)
    18. })
    19. }
    20. render() {
    21. const { value, value2 } = this.state
    22. return (
    23. <div>
    24. <h1>父组件h1>
    25. <p>value: {value}p>
    26. <p>value2: {value2}p>
    27. <button onClick={this.changeValue}>点击button>
    28. <DemoContext.Provider value={{
    29. value: value,
    30. value2: value2
    31. }}>
    32. <Child>Child>
    33. DemoContext.Provider>
    34. div>
    35. )
    36. }
    37. }

    3、通过Consumer创建一个消费者,用来接收传递的数据

    1. import React from "react";
    2. import DemoContext from "./DemoContext";
    3. export default class GrandSon extends React.Component {
    4. constructor(props) {
    5. super(props)
    6. }
    7. render() {
    8. return (
    9. <div>
    10. <h1>孙子组件h1>
    11. <DemoContext.Consumer>
    12. {/* Consumer中需要使用函数 */}
    13. {
    14. (value) => {
    15. return (
    16. <div>
    17. <p>value: {value.value}p>
    18. <p>value2: {value.value2}p>
    19. div>
    20. )
    21. }
    22. }
    23. DemoContext.Consumer>
    24. div>
    25. )
    26. }
    27. }

    中间组件:

    1. import React from "react";
    2. import GrandSon from "./GrandSon";
    3. export default class Child extends React.Component {
    4. render() {
    5. return (
    6. 子组件

    7. <GrandSon>GrandSon>
  • )
  • }
  • }
  •  

     

    使用状态管理实现跨级组件通信

    可以参考之前的博客:React-redux全局状态管理

    无关组件之间通信

    使用EventEmitter实现无关组件之间通信

    使用EventEmitter的步骤;

    1、安装events库

    npm install events

    2、创建 EventEmitter的实例

    1. import React from "react";
    2. import { EventEmitter } from "events";
    3. // 创建EventEmitter实例
    4. const DemoEvent = new EventEmitter()
    5. export default DemoEvent;

    3、发布事件

    使用emit("事件名",参数)发布事件

    1. import React from "react";
    2. import DemoEvent from './DemoEvent'
    3. export default class GrandSon extends React.Component {
    4. constructor(props) {
    5. super(props)
    6. this.state = {
    7. value: 0
    8. }
    9. this.changeValue = this.changeValue.bind(this)
    10. }
    11. changeValue() {
    12. this.setState({
    13. value: this.state.value + 1
    14. }, () => {
    15. console.log('changeValue 方法执行了 value: ', this.state.value)
    16. // 发送一个事件
    17. DemoEvent.emit('sendData', this.state.value)
    18. })
    19. }
    20. render() {
    21. return (
    22. <div>
    23. <h1>孙子组件 GrandSonh1>
    24. <p>{this.state.value}p>
    25. <button onClick={this.changeValue}>点击button>
    26. div>
    27. )
    28. }
    29. }

     4、订阅事件

    订阅事件可以使用addListener("事件名",回调函数),也可以使用on("事件名",回调函数)

    5、取消订阅

    取消订阅可以使用removeListener("事件名",回调函数),也可以使用off("事件名",回调函数)

    1. import React from "react";
    2. import DemoEvent from './DemoEvent'
    3. export default class GrandSon2 extends React.Component {
    4. constructor(props) {
    5. super(props)
    6. this.state = {
    7. value: 0
    8. }
    9. this.receiveData = this.receiveData.bind(this)
    10. }
    11. componentDidMount() {
    12. // 订阅事件
    13. DemoEvent.addListener('sendData', this.receiveData)
    14. }
    15. receiveData(data) {
    16. console.log('接收的数据 data: ', data)
    17. this.setState({
    18. value: data
    19. })
    20. }
    21. componentWillUnmount() {
    22. // 取消订阅
    23. DemoEvent.removeListener(this.receiveData)
    24. }
    25. render() {
    26. return (
    27. <div>
    28. <h1>孙子组件 GrandSon2h1>
    29. <p>{this.state.value}p>
    30. div>
    31. )
    32. }
    33. }

     

     

     使用状态管理实现无关组件通信

    可以参考之前的博客:React-redux全局状态管理

    补充:自己实现一个EventEmitter

    待续

  • 相关阅读:
    Revit如何快速做净高分析?方便、快捷的方法来了
    Nginx优化与防盗链
    ProcessDB实时/时序数据库——C/C++之数据订阅
    Partially ordered set
    企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图
    Acwing:730. 机器人跳跃问题(二分法)
    python数学建模--模拟退火算法求解一元函数极值
    java计算机毕业设计田径运动会管理系统源程序+mysql+系统+lw文档+远程调试
    前端开发:JS中字符串拼接的总结
    leetcode刷题
  • 原文地址:https://blog.csdn.net/Celester_best/article/details/126218290