React之生命周期

React之生命周期

旧版本,函数组件是没有生命周期的。新版本中通过useEffect触发函数的生命周期

一、基于类组件的生命周期

React的组件生命周期分为挂载阶段更新阶段销毁阶段。因为React的state不具有Vue的响应式,所以并没有create阶段

1、挂载阶段: 【组件被创建并插入到DOM中的过程】

  • constructor:组件被创建时调用,用于初始化状态和绑定方法。

  • static getDerivedStateFromProps:在组件被创建和重新渲染之前调用,用于根据props更新状态。

  • 【已废弃】componentWillMount: 组件即将挂载,已经被废弃,向下兼容请使用【UNSAFE_componentWillMount】

    • 执行1次
    • 特点:可以访问state、不能操作DOM
  • render: 对组件视图结构进行编译【必须定义的一个钩子】

    • 先默认执行1次,后去每次setState都会执行一次
    • 特点:可以访问state、不能操作DOM
  • componentDidMount: 组件挂载完成

    • 执行一次
    • 特点: 可以访问state,也能操作DOM
    • 应用场景:发送请求;初始化第三方插件
import { Component } from 'react'

export default class Home extends Component {
  state = {
    title: 'home'
  }
  clickUpdate = () => {
    this.setState({
      title: '主页'
    })
  }
  UNSAFE_componentWillMount(): void {
    console.log(this.state.title) // 'title'
    console.log(document.querySelector('.home_box')) // null
  }
  render() {
    console.log(this.state.title, 'render') // 'title'
    console.log(document.querySelector('.home_box'), 'render') // null
    return (
      <>
        <div className="home_box">{this.state.title}</div>
        <button onClick={this.clickUpdate}>获取DOM</button>
      </>
    )
  }
  componentDidMount(): void {
    console.log(this.state.title) // 'title'
    console.log(document.querySelector('.home_box')) // <div class="home_box">home</div>
  }
}

2、更新阶段【组件的props或state发生变化时的过程】

  • static getDerivedStateFromProps(props,state):在组件被重新渲染之前调用,用于根据props更新状态。[替代了componentWillReceiveProps]
  • shouldComponentUpdate: 是否要执行组件更新。如果显示的声明了该钩子,则必须返回一个布尔值,true:执行组件更新;false:不执行组件更新。如果没有显示的声明该钩子,则正常执行组件更新
    • 应用场景: 手动进行性能优化
    • 触发条件:state状态数据发生改变
    • 系统参数:nextProps: 更新后的props; nextState:更新后的state
    • 特点: 还没有完成数据和视图的更新
  • 【已废弃】componentWillUpdate: 即将执行组件更新: *已经被废弃,向下兼容请使用【UNSAFE_componentWillUpdate】
    • 触发条件:state状态数据发生改变
    • 系统参数:nextProps: 更新后的props; nextState:更新后的state
    • 特点: 还没有完成数据和视图的更新
  • render: 重新执行视图编译
    • 触发条件:state状态数据发生改变
    • 特点: 完成数据更新, 但是还没有完成视图更新
  • getSnapshotBeforeUpdate:在组件被重新渲染之前调用,用于获取更新前的DOM状态。[替换componetnWillUpdate]
  • componentDidUpdate:组件更新完成
    • 触发条件:state状态数据发生改变
    • 特点:已经完成数据和视图的更新
    • 系统参数:prevProps: 更新之前的props; prevState:更新之前的state【此时this.state是更新后的state】
    • 场景: 进行DOM操作、网络请求等副作用操作。
  • componentWillReceiveProps:组件接收的外部props属性数据发生改变的时候执行: *已经被废弃,向下兼容请使用【UNSAFE_componentWillReceiveProps】
    • 触发条件:props数据发生改变
    • 特点:已经完成数据和视图的更新
import { Component } from 'react'

export default class Home extends Component {
  state = {
    title: 'home'
  }
  clickUpdate = () => {
    this.setState({
      title: '主页'
    })
  }
  UNSAFE_componentWillMount(): void {
    console.log(this.state.title) // 'title'
    console.log(document.querySelector('.home_box')) // null
  }
  render() {
    console.log(this.state.title, 'render') // 'title'
    console.log(document.querySelector('.home_box'), 'render') // null
    return (
      <>
        <div className="home_box">{this.state.title}</div>
        <button onClick={this.clickUpdate}>获取DOM</button>
      </>
    )
  }
  componentDidMount(): void {
    console.log(this.state.title) // 'title'
    console.log(document.querySelector('.home_box')) // <div class="home_box">home</div>
  }

  // 更新阶段
  shouldComponentUpdate(
    nextProps: Readonly<{}>,
    nextState: Readonly<{ title: string }>,
    nextContext: any
  ): boolean {
    // nextProps: {}, nextState: 更新后的state, nextContext: {}
    console.log(nextProps, nextState, nextContext)
    if (this.state.title === nextState.title) {
      // 如果数据没有发生变化 则不执行组件更新, 即是不执行render()钩子
      return false
    }
    return true
  }

  // componentWillUpdate: 严格模式下eslint, 会报错
  // UNSAFE_componentWillUpdate: 这个在高版本React也废弃了, 但是在ESLint模式下也可以使用[向下兼容]
  UNSAFE_componentWillUpdate(
    nextProps: Readonly<{}>,
    nextState: Readonly<{}>,
    nextContext: any
  ): void {
    console.log(nextProps, nextState, nextContext, 'UNSAFE_componentWillUpdate')
  }

  componentDidUpdate(
    prevProps: Readonly<{}>,
    prevState: Readonly<{}>,
    snapshot?: any
  ): void {
    console.log(prevProps, prevState, snapshot, 'componentDidUpdate')
  }

  UNSAFE_componentWillReceiveProps(
    nextProps: Readonly<{}>,
    nextContext: any
  ): void {
    console.log(nextProps, nextContext, 'UNSAFE_componentWillReceiveProps')
  }
}

3、销毁阶段: 【组件从DOM中移除的过程】

  • componentWillUnmount:组件被移除前调用,可以进行清理操作,如取消定时器、取消订阅等。

4、补充

除了上述方法,还有一些其他的生命周期方法,如错误处理相关的方法(componentDidCatch、getDerivedStateFromError)和静态方法(getDerivedStateFromProps、getDerivedStateFromError)

需要注意的是,React 16.3之后,一些生命周期方法已经被废弃或改名,如componentWillMount、componentWillUpdate、componentWillReceiveProps等,建议使用新的方法来替代

  • 旧版生命周期图

在这里插入图片描述

  • 新版生命周期图
    在这里插入图片描述

二、函数组件的生命周期

React 18引入了一些新的生命周期方法,以便更好地管理组件的生命周期事件

  • useEffect: 【异步执行的,不会阻塞渲染】用于在组件挂载、更新或卸载时执行副作用操作。它可以替代旧的生命周期方法componentDidMount、componentDidUpdate和componentWillUnmount
import { useState, useEffect } from 'react'

const Home = () => {
  const [count, setCount] = useState(0)
  const add = () => {
    setCount(count + 1)
  }
  // 接收一个参数时:组件加载完成和组件状态更新时 执行
  useEffect(function () {
    console.log('zhw')
  })
  
  // 如果只希望函数挂载完后,执行一次,组件状态变化不再执行,可以传空数组
  useEffect(function () {
    console.log('zhw')
  }, [])
  
  // 接收参数二时,参数二是一个数组,用于指定依赖数据,用于当依赖数据变化时,执行一次回调
  // 1、组件挂载完后执行一次;2、仅仅当count的状态更新,执行一次
  useEffect(function () {
    console.log('zhw')
  }, [count])

  // 组件卸载之前按
  // 1、
  useEffect(function () {
    return function () {
      // 该子函数会在组件    即将卸载  和   状态更新 的时候,自动执行
      console.log('组件卸载了')
    }
  })  
  // 2、
  useEffect(function () {
    return function () {
      // 该子函数会在组件    仅仅在 即将卸载  的时候,自动执行
      console.log('组件卸载了')
    }
  }, []) 
  return (
    <>
    	<span>{count}</span>
      	<button onClick={add}>+</button>
    </>
  )
}
export default Home

  • useLayoutEffect: 在DOM更新之后同步执行[阻塞渲染],以确保在浏览器绘制之前执行副作用操作。

适用于需要在浏览器执行绘制和布局之前立即执行的副作用操作。

import { useLayoutEffect, useState } from 'react'

const Home = () => {
  const [count, setCount] = useState(0)
  const add = () => {
    setCount(count + 1)
  }
  useLayoutEffect(
    function () {
      console.log('useLayoutEffect')
    },
    [count]
  )
  return (
    <>
      <span>{count}</span>
      <button onClick={add}>+</button>
    </>
  )
}
export default Home
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

原谅我很悲

不要打赏哦,加个好友一起学习呗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值