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

Posted 学全栈的灌汤包

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

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

组件通信

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

比如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>
    )
  

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

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>
    )
  


参数验证

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

当然,如果你项目中默认继承了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

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

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

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

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

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

我们使用defaultProps就可以了

Header.defaultProps = 
  name: "默认名称"


子传父

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

在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

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

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

React之组件通信

  组件通信无外乎,下面这三种父子组件,子父组件,平行组件(也叫兄弟组件)间的数据传输。下面我们来分别说一下:

父子组件:

var Demo=React.createClass({
    getInitialState:function(){
        return{
            res:‘‘
        }
    },
    tap:function(e){
        var str=e.target.value;
        this.setState({res:str})
    },
    render:function(){
        return(
            <div>
                <h1>父组件</h1>
                <input type="text" onChange={this.tap}/>
                <Child name={this.state.res}/>
            </div>
        )
    }
})
var Child=React.createClass({
    render:function(){
        console.log(this.props)
        return(
            <div>
                <h1>子组件</h1>
                <p>{this.props.name}</p>
            </div>
        )
    }
})
ReactDOM.render(<Demo/>,document.getElementById(‘out‘))

这里我们通过设置默认状态,添加onchange事件,并把状态以默认属性的形式给子组件,然后通过this.props来获取。

说完了父子组件,那么子组件如何传递到父组件呢?

<script type="text/babel">
        var Demo=React.createClass({
    getInitialState:function(){
        return{
            res:‘‘
        }
    },
    render:function(){
        var _this=this;
        return(
            <div>
                <h1>父组件</h1>
                <p>{this.state.res}</p>
                <Child name={function(s){
                    _this.setState({res:s})
                }}/>
            </div>
        )
    }
})
var Child=React.createClass({
    tap:function(e){
        var str=e.target.value;
        console.log(str)
//        this.props.name==function
//        this.props.name(a)==function(s)
//        a==s
        this.props.name(str)
//        str==s
    },
    render:function(){
        console.log(this.props)
        return(
            <div>
                <h1>子组件</h1>
                <input type="text" onChange={this.tap}/>    
            </div>
        )
    }
})
ReactDOM.render(<Demo/>,document.getElementById(‘out‘))
    </script>

【子组件】控制自己的 state 然后告诉【父组件】的点击状态,然后在【父组件】中展示出来。

----------------------------------------------------------------------------------------------------------------------------------------------------

同级组件间的通讯复杂点,不过这里可以说点思路,假如这两个组件拥有相同的父组件可以将父组件作为桥梁,一个组件先传递给父组件,然后父组件再传递给兄弟组件。

另外还可以使用观察着模式,还有redux。这两个我还没完全理解,日后再说。

以上是关于React组件通信-父子组件间的通信的主要内容,如果未能解决你的问题,请参考以下文章

ReactJS学习笔记-父子组件间的通信

ReactJS学习笔记-父子组件间的通信

React之组件通信

「 VUE3 + TS + Vite 」父子组件间如何通信?

Vue 非父子组件通信方案

React 父子组件通信