react基础(六)— 父子组件通信

609 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

前言

大家好呀,我是L同学。在上篇文章中react基础(五)— 组件定义方式和生命周期,我们学习了react中组件定义方式和生命周期。接下来,我们学习各个组件间该如何通信。

父子组件通信 —— 父传子

在开发中我们写多个组件,而组件间存在嵌套关系,并且我们经常需要在组件之间相互通信。

父组件在展示子组件的时候,可能会传递一些数据给子组件。那么父组件的数据该怎么传递给子组件呢?

  • 父组件通过属性=值的方式给子组件传递数据
  • 子组件通过props参数获取父组件传递过来的数据

我们来看下子组件分别为类组件和函数组件,父组件是怎么传递的。

类组件

import React, { Component } from "react";

class ChildCpn extends Component {
render() {
  const {name, age, height} = this.props
  return (
    <h2>子组件展示数据:{name + ' ' + age + ' ' + height}</h2>   
  )
}
}

export default class App extends Component {
  render() {
    return (
      <div>
        <ChildCpn name="haha" age="18" height="1.88"></ChildCpn>
        <ChildCpn name="xixi" age="16" height="1.98"></ChildCpn>
      </div>
    )
  }
}

我们可以看到子组件成功获取到了父组件传递过来的数据,并进行了展示。 image.png

函数组件

import React, { Component } from 'react'

function ChildCpn(props) {
  const { name, age, height } = props
  return (
    <h2>子组件展示数据:{name + ' ' + age + ' ' + height}</h2>
  )
}

export default class App extends Component {
  render() {
    return (
      <div>
        <ChildCpn name="haha" age="18" height="1.88"></ChildCpn>
        <ChildCpn name="xixi" age="16" height="1.99"></ChildCpn>
      </div>
    )
  }
}

image.png

参数验证

对于传递给子组件的数据,有时候我们会进行验证,我们会通过prop-types库来进行参数验证。

在这个例子中我们给传递给子组件的数据做个验证。name数据是必须的,并且是字符串;age和height数据必须是Number类型;names数据必须是数组。

import React, { Component } from 'react'
import PropTypes from 'prop-types'

function ChildCpn(props) {
  const { name, age, height, names } = props
  return (
    <div>
      <h2>{name + ' ' + age + ' ' + height}</h2>
      <ul>
        {
          names.map(item => {
            return <li>{item}</li>
          })
        }
      </ul>
    </div>
  )
}

ChildCpn.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
  height: PropTypes.number,
  names: PropTypes.array
}

export default class App extends Component {
  render() {
    return (
      <div>
        <ChildCpn name="haha" age='18' height={1.88} names={['小王', '小何', '小白']}></ChildCpn>
      </div>
    )
  }
}

我们可以看到当父组件传递给子组件的age数据为字符串时,会报警告,期待是Number类型,但是获取到的是String类型。 image.png

那么如果父组件没有传递给子组件数据,子组件还想要使用,那么我们可以使用defaultProps指定默认值。

ChildCpn.defaultProps = {
  name: 'hahahaha',
  age: 20,
  height: 1.89,
  names: ['abc', 'cba']
}

我们来测试下。往父组件中增加一个子组件,不传递数据,会使用默认值。

<ChildCpn></ChildCpn>

我们可以看到页面上渲染的是默认值。

image.png 同样,类组件添加类型验证可以用上述方法。除了这一种,类组件还可以这样进行类型验证。

class ChildCpn2 extends Component {
  // es6中的class fields写法 
  static propTypes = {

  }

  static defaultProps = {
    name: 'hahahaha',
    age: 20,
    height: 1.89,
    names: ['abc', 'cba']
  }

}

第一种ChildCpn.defaultProps = {}方式相当于给类添加了静态方法。

父子组件通信 —— 子传父

除了父组件给子组件传递数据,有时候,我们还需要子组件给父组件传递数据。

在react中,子组件传递数据给父组件同样使用props,只是让父组件给子组件传递一个回调函数,在子组件中调用这个回调函数就可以。

接下里,我们做个小案例。需求是这样子的,我们把按钮封装到子组件CounterButton中,点击这个按钮,CounterButton就发生了点击事件,将内容传递到父组件,修改counter的值。

import React, {Component} from 'react'

class CounterButton extends Component {
render() {
  const {onClick1} = this.props
  return <button onClick={onClick1}>+1</button>
}
}

export default class App extends Component {
  constructor() {
    super()
    this.state = {
      counter: 0
    }
  }
  render() {
    return (
      <div>
        <h2>当前计数:{this.state.counter}</h2>
        <CounterButton onClick1={() => {this.increment()}}></CounterButton>
      </div>
    )
  }

  increment() {
    this.setState({
      counter: this.state.counter + 1
    })
  }
}

我们可以看到点击子组件中的按钮,父组件中的数据发生了改变。

image.png