• React组件通信-父子组件间的通信


    React父子组件通信

    认识组件嵌套

    组件之间存在嵌套关系

    在之前的案例中,我们只是创建了一个组件App;

    如果我们一个应用程序将所有的逻辑都放在一个组件中,那么这个组件就会变成非常的臃肿和难以维护;

    所以组件化的核心思想应该是对组件进行拆分,拆分成一个个小的组件;

    再将这些组件组合嵌套在一起,最终形成我们的应用程序;

    在这里插入图片描述

    上面的嵌套逻辑如下,它们存在如下关系

    App组件是Header、Main、Footer组件的父组件;

    import React, { Component } from 'react'
    
    import Header from './Header'
    import Main from "./Main"
    import Footer from './Footer'
    
    export class App extends Component {
      render() {
        return (
          <div>
            <Header/>
            <Main/>
            <Footer/>
          </div>
        )
      }
    }
    
    export default App
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    Main组件是Banner、ProductList组件的父组件

    import React, { Component } from 'react'
    import Banner from './Banner'
    import ProductList from './ProductList'
    
    export class Main extends Component {
      render() {
        return (
          <div>
            <div>Main</div>
            <Banner/>
            <ProductList/>
          </div>
        )
      }
    }
    
    export default Main
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    组件通信

    在开发过程中,我们会经常遇到需要组件之间相互进行通信

    比如App可能使用了多个Header,每个地方的Header展示的内容不同,那么我们就需要使用者传递给Header一些数据,让其进行展示;

    又比如我们在Main中一次性请求了Banner数据和ProductList数据,那么就需要传递给他们来进行展示;

    也可能是子组件中发生了事件,需要由父组件来完成某些操作,那就需要子组件向父组件传递事件;

    总之,在一个React项目中,组件之间的通信是非常重要的环节


    父传子

    父组件在展示子组件时,可能会传递一些数据给子组件

    父组件通过 属性=值的形式来传递给子组件数据;

    子组件通过 this.props 获取父组件传递过来的数据;

    例如我们来看这样一个需求, 父组件将定义的数组books传递给子组件, 由子组件进行展示

    将数组传递给子组件

    export class App extends Component {
      constructor() {
        super()
    
        this.state = {
          books: [
            {name: "算法导论", price: 79},
            {name: "数据结构", price: 69},
            {name: "漫画算法", price: 59},
          ]
        }
      }
    
      render() {
        const { books } = this.state
    
        return (
          <div>
            {/* 将数据传递给子组件 */}
            <Header books={books}/>
          </div>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在子组件接受父组件传递的数据

    export class Header extends Component {
      render() {
        // 接受父组件传递过来的参数
        const { books } = this.props
        return (
          <div>
            <ul>
              {
                books.map(item => {
                  return (
                    <li key={item.name}>
                      名称: {item.name} 价格: {item.price}
                    </li>
                  )
                })
              }
            </ul>
          </div>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    参数验证

    对于传递给子组件的数据,有时候我们可能希望进行验证,特别是对于大型项目来说

    当然,如果你项目中默认继承了Flow或者TypeScript,那么直接就可以进行类型验证;

    但是,即使我们没有使用Flow或者TypeScript,也可以通过 prop-types 库来进行参数验证;

    从 React v15.5 开始,React.PropTypes 已移入另一个包中:prop-types 库

    使用方法, 先在子组件中导入PropTypes, 再对传递过来的元素添加类型限制即可

    import React, { Component } from 'react'
    
    // 导入PropTypes
    import PropTypes from 'prop-types'
    
    export class Header extends Component {
      render() {
        const { books, name, age } = this.props
        return (
          <div>
            <div>名字: {name} 年龄: {age}</div>
            <ul>
              {
                books.map(item => {
                  return (
                    <li key={item.name}>
                      名称: {item.name} 价格: {item.price}
                    </li>
                  )
                })
              }
            </ul>
          </div>
        )
      }
    }
    
    // 对参数添加类型的限制
    Header.propTypes = {
      // 表示传入的类型是要求一个数组, 并且必传
      books: PropTypes.array.isRequired,
      // 传入类型string, 非必传
      name: PropTypes.string,
      // 传入类型number, 非必传
      age: PropTypes.number
    }
    
    export default Header
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    更多的验证方式,可以参考官网:https://zh-hans.reactjs.org/docs/typechecking-with-proptypes.html

    比如验证数组,并且数组中包含哪些元素;

    比如验证对象,并且对象中包含哪些key以及value是什么类型;

    比如某个原生是必须的,使用 requiredFunc: PropTypes.func.isRequired

    如果没有传递,我们希望有默认值呢?

    我们使用defaultProps就可以了

    Header.defaultProps = {
      name: "默认名称"
    }
    
    • 1
    • 2
    • 3

    子传父

    某些情况,我们也需要子组件向父组件传递消息

    在vue中是通过自定义事件来完成的;

    在React中同样是通过props传递消息,只是让父组件给子组件传递一个回调函数,在子组件中调用这个函数即可;

    我们这里来完成一个案例

    将计数器案例进行拆解;

    将按钮封装到子组件中:CounterButton;

    CounterButton发生点击事件,将内容传递到父组件中,修改counter的值;

    演示代码

    父组件传递一个事件给子组件CounterButton

    import React, { Component } from 'react'
    import ConterButton from './c-cpn/ConterButton'
    
    export class App extends Component {
      constructor() {
        super()
    
        this.state = {
          conter: 100
        }
      }
    
      changeConter(conter) {
        this.setState({ conter: this.state.conter + conter })
      }
    
      render() {
        const { conter } = this.state
    
        return (
          <div>
            <h2>{conter}</h2>
            {/* 向子组件中传入一个事件 */}
            <ConterButton getConter={conter => this.changeConter(conter)}/>
          </div>
        )
      }
    }
    
    export default App
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    子组件在按钮发生点击时, 对父组件的传递的函数进行回调, 并传入一个参数出去

    import React, { Component } from 'react'
    
    export class ConterButton extends Component {
    
      btnClick(conter) {
        // 当按钮发生点击事件时, 对父组件传递过来的函数进行回调
        this.props.getConter(conter)
      }
    
      render() {
        return (
          <div>
            <button onClick={() => this.btnClick(-1)}>-1</button>
            <button onClick={() => this.btnClick(1)}>+1</button>
          </div>
        )
      }
    }
    
    export default ConterButton
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
  • 相关阅读:
    一文读懂 MongoDB 和 MySQL 的差异
    Java 第2天:第一个接口
    nginx(六十一)proxy模块(二)修改发往上游的请求
    React学习总结
    [SWPUCTF 2022 新生赛]善哉善哉(隐写,新佛曰,MD5)
    从0开始C++(五):友元函数&运算符重载
    区块链的量子威胁:解密数学漏洞
    构建并训练简单的CNN
    虚幻引擎:如何在工程里面添加插件
    Unity 之 Material (材质)渲染3D对象的重要组件
  • 原文地址:https://blog.csdn.net/m0_71485750/article/details/126633385