组件的生命周期 | 青训营笔记

52 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的的第13天

通过查看React文档和一些资料,增强对组件生命周期的了解

1. 认识生命周期

很多的事物都有从创建到销毁的整个过程,这个过程称之为是生命周期;而React组件也有自己的生命周期。

生命周期和生命周期函数的关系:

  • 生命周期是一个抽象的概念,在生命周期的整个过程,分成了很多个阶段;
    • 比如装载阶段(Mount) ,组件第一次在DOM树中被渲染的过程;
    • 比如更新过程(Update) ,组件状态发生变化,重新更新渲染的过程;
    • 比如卸载过程(Unmount) ,组件从DOM树中被移除的过程;
  • React内部为了告诉我们当前处于哪些阶段,会对我们组件内部实现的某些函数进行回调,这些函数就是生命周期函数:
    • 比如实现componentDidMount函数:组件已经挂载到DOM上时,就会回调;
    • 比如实现componentDidUpdate函数:组件已经发生了更新时,就会回调;
    • 比如实现componentWillUnmount函数:组件即将被移除时,就会回调;
    • 我们可以在这些回调函数中编写自己的逻辑代码,来完成自己的需求功能;

我们谈React生命周期时,主要谈的类的生命周期,因为函数式组件是没有生命周期函数的

2. 生命周期解析

最基础、最常用的生命周期函数如下图所示:

image-20220730215428118

上图第一个区域解析:

  • 当我们挂载一个组件时,会先执行constructor构造方法来创建组件
  • 紧接着调用render函数,获取要渲染的DOM结构(jsx),并且开始渲染DOM
  • 当组件挂载成功(DOM渲染完成),会执行componentDidMount生命周期函数

上图第二个区域解析:

  • 当我们通过修改props,或者调用setState修改内部状态,或者直接调用forceUpdate时会重新调用render函数,进行更新操作
  • 当更新完成时,会回调componentDidUpdate生命周期函数

上图第三个区域解析:

  • 当我们的组件不再使用,会被从DOM中移除掉(卸载)
  • 这个时候会回调componentWillUnmount生命周期函数

3. 生命周期函数

3.1 constructor

 constructor(props)

如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。

constructor中通常只做两件事情:

  • 通过给 this.state 赋值对象来初始化内部的state
  • 为事件绑定实例(this)

3.2 componentDidMount

 componentDidMount()

componentDidMount() 会在组件挂载后(插入 DOM 树中)立即调用。

componentDidMount中通常进行如下操作

  • 进行依赖于DOM的操作
  • 在此处发送网络请求(官方建议)
  • 可以在此处添加一些订阅(会在componentWillUnmount取消订阅)

3.3 componentDidUpdate

 componentDidUpdate(prevProps, prevState, snapshot)

componentDidUpdate() 会在组件更新后被调用,首次渲染不会执行此方法。

  • 当组件更新后,可以在此处对 DOM 进行操作
  • 更新前后的 props 进行了比较,也可以选择在此处进行网络请求;(例如,当 props 未发生变化时,则不会执行网络请求)
 componentDidUpdate(prevProps) {
   // 典型用法(不要忘记比较 props):
   if (this.props.userID !== prevProps.userID) {
     this.fetchData(this.props.userID);
   }
 }

3.4 componentWillUnmount

 componentWillUnmount()

componentWillUnmount() 会在组件卸载及销毁之前直接调用。

  • 在此方法中执行必要的清理操作
  • 例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等

代码验证所有的生命周期函数:

 import React, { Component } from 'react'
 // Cpn组件挂载到 App组件上,通过button按钮切换显示。用于验证componentWillUnmount方法
 class Cpn extends Component {
     render() {
         return (
             <h2>我是Cpn组件</h2>
         )
     }
     componentWillUnmount() {
         console.log("执行了Cpn组件的componentWillUnmount方法")
     }
 }
 ​
 export default class App extends Component {
     constructor() {
         super()
         this.state = {
             counter: 0,
             isCpnShow: true
         }
         console.log("执行了App组件的constructor方法")
     }
     render() {
         console.log("执行了App组件的render方法")
 ​
         return (
         <div>我是App组件
             <h2>当前计数:{this.state.counter}</h2>
             <button onClick={e => this.increase()}> +1 </button>
             <hr/>
             <button onClick={e => this.changeCpnShow()}>切换</button>
             {/*显示或删除组件Cpn */}
             {this.state.isCpnShow && <Cpn />}
         </div>
         )
     }
     changeCpnShow() {
         this.setState({
             isCpnShow: !this.state.isCpnShow
         })
     }
 
     increase() {
         this.setState({
             count: this.state.counter + 1
         })
     }
 
     componentDidUpdate() {
         console.log("执行了App组件的componentDidUpdate方法")
     }
     componentDidMount() {
         console.log("执行了App组件的componentDidMount方法")
     }
 }

3.5 不常用生命周期

除了上面介绍的生命周期函数之外,还有一些不常用的生命周期函数:

  • getDerivedStateFromProps:state 的值在任何时候都依赖于 props时使用;该方法返回一个对象来更新state
  • getSnapshotBeforeUpdate:在React更新DOM之前回调的一个函数,可以获取DOM更新前的一些信息(比如说滚动位置)
  • shouldComponentUpdate:该生命周期函数主要用于性能优化

image-20220730221450727

更详细的生命周期相关的内容,可以参考官网:zh-hans.reactjs.org/docs/react-…