React组件间通信方式, React生命周期理解

本文详细介绍了React组件间的通信方式,包括父传子props、props.children、子传父回调以及跨组件通信的context机制。同时,文章还探讨了React组件的生命周期,包括不同版本的生命周期变化,以及各生命周期函数的作用,如constructor、render、componentDidMount等,并提供了相关代码示例。
摘要由CSDN通过智能技术生成

React

React组件间通信

  • 父级向子级通信
  • 子级向父级通信
  • 同级组件间通信
  • 跨组件通信 -context

在React.js 中, 组件间数据是自上向下流动(传递)的, 也就是一个父组件可以把它的 state/props通过 props 传参的方式传递给它的子组件, 但是子组件不能直接修改父组件的 state/props, 所以说 React中是单向数据流的.

如果子组件需要修改父组件的状态(数据), 是通过回调的方式来完成的.

父传子 props

props 传参的形式不仅可以传递数据, 还可以传递结构(即: 还可以通过props传递组件结构).

React中,父组件给子组件传递数据, 最常用的是通过 props 属性的方式传值. 通过在父组件中, 给子组件标签添加一个属性传值, 可以在子组件的 props 中接收该值, 具体代码演示如下:

src/Parent.js 父组件

import React, {Component} from 'react'
import Children from './Children'

class Parent extends Component {
    constructor(props) {
        super(props);
        this.state = {
            person:{
                name:'Gene',
            }
        }
    }
    render() {
        return (
            <div>
                <Children person={this.state.person}/>
            </div>
        )
    }
}
export default Parent

src/Children.js 子组件代码

import React, {Component} from 'react'

class Children extends Component {
    render() {
        const {person} = this.props;
        return (
            <div>
                <h2>hello, 我是children {person.name}!</h2>
            </div>
        )
    }
}
export default Children

props.children 父传子

props.children介绍
每个组件都可以获取到 props.children . 它包含组件的开始标签和结束标签中间的内容, 我们同样可以依据这种方式给子组件中传递数据,通常我们用这种方式传递标签数据 .
src/parent.js 父组件代码

import React, {PureComponent} from 'react'
import Children from './Children'
class Parent extends PureComponent {
  render() {
      return (
          <div>
              <Children>
                  <p>我是p1</p>
                 <p>我是p2</p>
                  <p>我是p3</p>
              </Children>
          </div>
      )
 }
}
export default Parent

src/children .js 子组件代码

import React {PureComponent} from 'react'
class Children extends PureComponent {
 render() {
  const {children} = this.props
  return (
           <div>
              <h1>我是儿子组件</h1>
              {children}
            </div>
			)
		}
}
export default Children

这种传参方式有一点儿类似于Vue 中的slot插槽传参,这样理解可能有点儿不准确, 暂且先这么理解

子传父 回调

子组件给父组件传递数据也是利用的是props传参的方式, 通过给子组件传入一个回调函数, 在子组件的props 中接收, 在子组件中调用该回调函数, 传入参数, 即可以在父组件中接收到子组件的数据. 具体演示代码如下:

src/parent.js 父组件

import React, {Component} from 'react'
import Children from './Children'

class Parent extends Component {
    constructor(props) {
        super(props);
        this.getChildrenData=this.getChildrenData.bind(this)
    }

    getChildrenData(data){
        console.log('%c接收子组件的数据 -->',"color:red",data);
    }
    render() {
        return (
            <div>
                <Children getChildrenData={this.getChildrenData} />
            </div>
        )
    }
}
export default Parent

src/children.js 子组件

import React, {Component} from 'react'
import Children from './Children'

class Parent extends Component {
    constructor(props) {
        super(props);
        this.getChildrenData=this.getChildrenData.bind(this)
    }

    getChildrenData(data){
        console.log('%c接收子组件的数据 -->',"color:red",data);
    }
    render() {
        return (
            <div>
                <Children getChildrenData={this.getChildrenData} />
            </div>
        )
    }
}
export default Parent

跨组件通信 context

当组件的嵌套太深, 通过 props 层层传参的方式会比较麻烦, 此时我们可以考虑使用 context 的方式传参.

context 一般不建议在项目中直接使用, 这种方式一般是给第三方的 api 来使用的,比如 redux,

如果不借助于第三方的库, 通过 context 方式通信也比较麻烦, 故我们此处不再贴详细代码, 如想了解, 详见官网描述

注意 在使用不熟练时, 最好不要在项目中使用 context , context 一般给第三方库使用.

React组件的生命周期

所谓的生命周期是指某个事物从开始到结束的各个阶段, 当然在React.js 中指的是组件从创建到销毁的过程, React.js在这个过程中的不同阶段调用的函数, 通过这些函数, 我们可以更加精确的对组件进行控制, .

React的生命周期演变

React 16.3 之前

  1. 挂载阶段
- constructor
- componentWillMount
- render
- componentDidMount
  1. 更新阶段
#1. 父组件更新引起子组件更新
	- componentWillReceiveProps(nextProps)
	- shouldComponentUpdate(nextProps, nextState)
	- componentWillUpdate(nextProps, nextState)
	- render
	- componentDidUpdate(prevProps, prevState)
#2. 组件自身更新
	- shouldComponentUpdate
	- componentWillUpdate
	- render
	- componentDidUpdate
  1. 挂载/销毁阶段
- componentWillUnmount

React16.3 之后

  1. 挂载阶段
- constructor
- static getDerivedStateFromProps(props, state) 
	- 注意: 在静态生命周期函数里没有this,要注意this问题
- render
- componentDidMount
  1. 更新阶段
#1. 父组件更新引起子组件更新
	- static getDerivedStateFromProps(props, state)
	- shouldComponentUpdate()
	- componentWillUpdate()
	- render()
	- getSnapshotBeforeUpdate()
	- componentDidUpdate()

#2. 组件自身更新
	- shouldComponentUpdate()
	- componentWillUpdate()
	- render()
	- getSnapshotBeforeUpdate() 
	- componentDidUpdate()
  1. 卸载阶段
- componentWillUnmount
  1. 错误处理
- static getDerivedStateFromError() 
- componentDidCatch(error, info)  

将来生命周期替代方法

useEffect() 副作用 (用来替代先行生命周期)

React生命周期演进参考图

生命周期函数作用详解

constructor(props)

constructor 是类的构造函数, 也是组件初始化函数, 一般情况下, 我们会在这个阶段做一些初始化的工作

  • 初始化 state
  • 处理事件绑定函数的 this

render()

render 方法是 Class 组件必须 实现的一个方法.

static getDerivedStateFromProps(props,state)

该方法会在 render 方法之前调用, 无论是挂载阶段还是更新阶段, 它的存在只有一个目的: 让组件在 props 变化时更新 state

componentDidMount()

在组件挂载后(render的内容插入 DOM树中)调用, 通常这个阶段, 我们可以

  • 操作 DOM 节点
  • 发送请求

getSnapshotBeforeUpdata(prevProps,prevState)

该方法在 render() 之后, 但是在输出到 DOM 之前执行, 用来获取渲染之前的文档快照, 当我们想在当前一次更新前获取上次的DOM 状态, 可以在这里进行处理, 该函数的返回值将作为参数传递给下个声明周期函数 componentDidUpdate

但是该函数并不常用

componentDidUpdate()

该函数会在 DOM 更新后立即调用, 首次渲染不会调用该方法 , 我们可以在这个函数中对渲染后的 DOM 进行操作

componentWillUnmount()

该方法会在组件卸载及销毁前调用, 我们可以在这里做一些清理工作, 如: 组件内的定时器, 未完成的请求等.

错误处理

  1. 错误捕获, 不捕获事件中的错误
  2. 在父级组件中捕获子组件中的错误.
    当渲染过程, 生命周期, 或子组件的构造函数中抛出错误时, 会调用如下方法:
  • static getDerivedStateFromError()
  • componentDidCatch()

static getDerivedStateFromError()

该方法用来获取子组件抛出的错误,返回值是一个对象,该对象被存储在 state 中,在后续的 render 方法中就可以根据这个对象的值来进行处理,如:显示不同的 UI

static getDerivedStateFromError(error)

**componentDidCatch() ** // 将来版本会有变化

该方法与 getDerivedStateFromError() 类似,但是也有不同的地方:

  • 该方法会有一个记录详细错误堆栈信息的 info 参数
  • 该方法可以执行一些额外的操作:打印错误、上报错误信息……
componentDidCatch(error, info)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值