SakuraSnow's blog SakuraSnow's blog
首页
  • JavaScript
  • TypeScript
  • Vue
  • React
  • Git
  • Node
  • Linux
  • 技术文档
  • 博客搭建
  • 数据结构
  • leetcode
  • 关于
  • 友链
  • 收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

SakuraSnow

一只前端咸鱼
首页
  • JavaScript
  • TypeScript
  • Vue
  • React
  • Git
  • Node
  • Linux
  • 技术文档
  • 博客搭建
  • 数据结构
  • leetcode
  • 关于
  • 友链
  • 收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 核心概念

    • React组件的生命周期
      • 序
      • 旧版生命周期
        • 总览
        • constructor(props, context, updater)
        • componentWillMount()
        • render()
        • componentDidMount()
        • componentWillReceiveProps(nextProps)
        • shouldComponentUpdate(nextProps, nextState)
        • componentWillUpdate(nextProps, nextState)
        • componentDidUpdate(nextProps, nextState)
        • componentWillUnmount()
      • 新版生命周期
        • 总览
        • 删除的API
        • static getDerivedStateFromProps(props, state)
        • getSnapshotBeforeUpdate()
      • 参考
  • 高级指引

  • React笔记
  • 核心概念
SakuraSnow
2020-08-30

React组件的生命周期

# 序

用惯了vue用react的生命周期总有一丝怪异啊,不过这并不妨碍我记点笔记

生命周期仅存在于类组件中,函数组件每次调用都是重新运行函数,旧的组件会被立刻销毁

# 旧版生命周期

# 总览

旧版生命周期对应React的版本小于16.3 file

# constructor(props, context, updater)

React借用class类的constructor充当初始化钩子。

React规定constructor有三个参数,分别是props、context和updater。

  • props是属性,它是不可变的。
  • context是上下文
  • updater是包含一些更新方法的对象,this.setState最终调用的是this.updater.enqueueSetState方法,this.forceUpdate最终调用的是this.updater.enqueueForceUpdate方法,所以这些API更多是React内部使用,暴露出来是以备开发者不时之需。

在React中,constructor需要先调用super(props),用于初始化this和props,详情可以看这里 (opens new window)

constructor生命周期钩子中可以初始化this.state。

也可以使用下面的代码初始化state

import React, { Component } from 'react';

class App extends Component {
    state = {
        name: 'biu',
    };
}

export default App;
1
2
3
4
5
6
7
8
9

constructor只会在组件创建时调用一次,之后的组件更新不会再调用constructor

# componentWillMount()

这是组件挂载到DOM之前的生命周期钩子。

在某些特殊情况下,这个函数有可能会被调用两次,

  • 服务端渲染
  • Fiber的Reconciliation过程中打断了这个生命周期

所以有可能出现一些bug,不过这个生命周期好像也没什么用,所以建议尽量不要使用

# render()

作为一个组件,最核心的功能就是把元素挂载到DOM上,所以render生命周期钩子是一定会用到的。

render会返回一个虚拟DOM,这个虚拟DOM会被挂载到虚拟DOM树中,最终渲染到页面的真实DOM中

render可能不只运行一次,只要需要重新渲染,就会重新运行

在render中最好不要使用setState,因为可能会导致无限递归渲染

# componentDidMount()

这是组件挂载到DOM之后的生命周期钩子,这个时候的组件已经就绪,你可以随心所欲的操作数据了

通常情况下,我们会将网络请求、启动计时器等初始化操作,书写到该函数中

# componentWillReceiveProps(nextProps)

componentWillReceiveProps生命周期钩子只有一个参数,即更新后的props,这个生命周期不会在组件初始化时触发

该声明周期函数可能在两种情况下被触发:

  • 组件接收到了新的属性。
  • 组件没有收到新的属性,但是由于父组件重新渲染导致当前组件也被重新渲染。

同样,因为Fiber机制的引入,这个生命周期钩子有可能会多次触发。

# shouldComponentUpdate(nextProps, nextState)

这个生命周期钩子用于指示React是否要重新渲染该组件(通过返回true或者false), 主要用于性能优化

shouldComponentUpdate生命周期钩子默认返回true。也就是说,默认情况下,只要组件触发了更新,组件就一定会更新。

如果开发者调用this.forceUpdate强制更新,React组件会无视这个钩子

# componentWillUpdate(nextProps, nextState)

组件即将被重新渲染时调用这个钩子,具体来说是在shouldComponentUpdate生命周期钩子返回true,或者调用this.forceUpdate之后。

在componentWillUpdate中最好不要使用setState,因为可能会导致无限递归渲染

同样,因为Fiber机制的引入,这个生命周期钩子有可能会多次调用。

# componentDidUpdate(nextProps, nextState)

这是组件更新之后触发的生命周期钩子,在这里可以拿到更新后的DOM

在componentDidUpdate中最好不要使用setState,因为可能会导致无限递归渲染

# componentWillUnmount()

这是组件卸载之前的生命周期钩子,通常在该函数中销毁一些组件依赖的资源,比如计时器或者注册的全局事件

# 新版生命周期

# 总览

file

# 删除的API

  • componentWillMount
  • componentWillUpdate
  • componentWillReceiveProps

旧版的生命周期函数非常的对称,有componentWilUpdate对应componentDidUpdate,有componentWillMount对应componentDidMount;也考虑到了因为父组件引发渲染可能要根据props更新state的需要,所以有componentWillReceiveProps。

但是,这个生命周期函数的组合在Fiber之后就显得不合适了,如果开启async rendering,在render函数之前的所有函数,都有可能被执行多次。所以为了安全考虑,react废弃了这三个API

# static getDerivedStateFromProps(props, state)

getDerivedStateFromProps是一个静态函数,所以函数体内不能访问this,简单说,就是一个纯函数

static getDerivedStateFromProps(nextProps, prevState) {
	// 根据nextProps和prevState计算出预期的状态改变,返回结果会被送给setState
}
1
2
3

getDerivedStateFromProps是componentWillReceiveProps的替代品,但是前者比后者更安全,因为不能访问this,就可以避免开发者做很多预料之外的操作,因为这个hook的设计初衷是根据props更新state

# getSnapshotBeforeUpdate()

这函数会在render之后执行,而执行之时DOM元素还没有被更新,开发者可以在这时获取dom的一些信息(比如保存网页滚动条位置)

函数的返回值会作为componentDidUpdate的第三个参数传入

  getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log('#enter getSnapshotBeforeUpdate');
    return 'foo';
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log('#enter componentDidUpdate snapshot = ', snapshot);
  }
1
2
3
4
5
6
7
8

# 参考

React生命周期 (opens new window)

React v16.3之后的组件生命周期函数 (opens new window)

#React#前端
上次更新: 2022/03/05, 15:57:30
BaKa也能看懂的react-router和redux教程

BaKa也能看懂的react-router和redux教程→

最近更新
01
009-Palindrome Number[回文数]
03-10
02
008-String to Integer (atoi)[字符串转整数]
03-10
03
004-Reverse-integer[整数反转]
03-09
更多文章>
Theme by Vdoing | Copyright © 2019-2022 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×