前言

所谓的生命周期就是指某个事物从开始到结束的各个阶段,就好像是把人的出生到死亡分成一个个阶段,你肯定是在出生阶段起名字,而不会在成年或者死亡的阶段去起名字。当然在 React.js 中指的是组件从创建到销毁的过程,React 实例从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 React 的生命周期,各个阶段有相对应的事件钩子,用户可以在特定的阶段调用特定的方法。每个阶段组件内部的属性都是不一样的,所以一般特定的钩子做特定的事。

一、React生命周期图

【1】过去

【2】现在

二、React生命周期演变

这么多生命周期钩子,实际上总结起来只有三个过程:挂载、更新、卸载,挂载和卸载只会执行一次,更新会执行多次。

一个完整的React组件生命周期会依次调用如下钩子

【1】生命周期演变

React版本 挂载阶段 更新阶段 卸载阶段
之前(React 16.3 之前)
  • constructor
  • componentWillMount
  • render
  • componentDidMount
  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate
componentWillUnmount
现在
  • constructor
  • getDerivedStateFromProps
  • render
  • componentDidMount
  • getDerivedStateFromProps
  • shouldComponentUpdate
  • render
  • getSnapshotBeforeUpdate
  • componentDidUpdate
componentWillUnmount

【2】废弃和新增

原来(React v16.0前)的生命周期在React v16推出的Fiber之后就不合适了,因为如果要开启async rendering,在render函数之前的所有函数,都有可能被执行多次。所以除了shouldComponentUpdate,其他在render函数之前的所有函数(componentWillMount,componentWillReceiveProps,componentWillUpdate)都被getDerivedStateFromProps替代。

以下生命周期钩子将被逐渐废弃,看出特点了么,都是带有will的钩子

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

引入了以下两个生命周期钩子

  • getDerivedStateFromProps
  • getSnapshotBeforeUpdate

【3】注意

  1. getDerivedStateFromProps前面要加上static保留字,声明为静态方法,不然会被react忽略掉
  2. getDerivedStateFromProps里面的this为undefined

三、React生命周期方法介绍

【1】constructor(props):初始化钩子函数

constructor()中完成了React数据的初始化,它接受两个参数:props和context,当想在函数内部使用这两个参数时,需使用super()传入这两个参数。如果没有初始化状态(state),并且没有绑定方法,通常不需要为 React 组件实现一个构造函数。

注意:

  1. 只要使用了constructor()就必须写super(),否则会导致this指向错误。
  2. 不需要在构造函数中调用 setState(),只需将初始状态设置给 this.state 即可 。

React 构造函数通常只用于两个目的:

  1. 通过分配一个对象到this.state来初始化本地state
  2. 将事件处理程序方法绑定到实例
constructor(props) {super(props);// 不要这样做this.state = { color: props.color };
}

【2】componentWillMount():组件将要挂载时触发的函数

这是组件挂载到DOM之前的生命周期钩子。componentWillMount()一般用的比较少,它更多的是在服务端渲染时使用。它代表的过程是组件已经经历了constructor()初始化数据后,但是还未渲染DOM时。

【3】render():组件挂载时触发的函数

render函数是类组件中唯一必须的方法,其余生命周期不是必须要写。 组件渲染时会走到该生命周期,展示的组件都是由 render() 生命周期的返回值来决定。render函数会插入jsx生成的dom结构,react会生成一份虚拟dom树,在每一次组件更新时,在此react会通过其diff算法比较更新前后的新旧DOM树,比较以后,找到最小的有差异的DOM节点,并重新渲染。

【4】componentDidMount():组件挂载完成时触发的函数

这是组件挂载到DOM之后的生命周期钩子。组件第一次渲染完成,此时dom节点已经生成,可以在这里调用ajax请求,返回数据setState后组件会重新渲染

【5】componentWillUnmount ():组件将要销毁时触发的函数

这是组件卸载之前的生命周期钩子,在此处完成组件的卸载和数据的销毁。

【6】componentWillReceiveProps (nextProps):父组件中改变了props传值时触发的函数

  1. 在接受父组件改变后的props需要重新渲染组件时用到的比较多
  2. 接受一个参数nextProps
  3. 通过对比nextProps和this.props,将nextProps的state为当前组件的state,从而重新渲染组件
  componentWillReceiveProps (nextProps) {nextProps.isOpen !== this.props.isOpen && this.setState({isOpen:nextProps.isOpen}, () => {//将state更新为nextProps,在setState的第二个参数(回调)可以打印出新的state})
}

【7】shouldComponentUpdate(nextProps,nextState):是否要更新组件时触发的函数

  1. 这个生命周期钩子是一个开关,判断是否需要更新,主要用来优化性能(部分更新),如果开发者调用this.forceUpdate强制更新,React组件会无视这个钩子。
  2. 对于组件来说,只有状态发生改变,才需要重新渲染。所以shouldComponentUpdate生命周期钩子暴露了两个参数,开发者可以通过比较this.props和nextProps、this.state和nextState来判断状态到底有没有发生改变,再相应的返回true或false。
  3. 唯一用于控制组件重新渲染的生命周期,由于在react中,setState以后,state发生变化,组件会进入重新渲染的流程,在这里return false可以阻止组件的更新
  4. 因为react父组件的重新渲染会导致其所有子组件的重新渲染,这个时候其实我们是不需要所有子组件都跟着重新渲染的,因此需要在子组件的该生命周期中做判断

【8】componentWillUpdate (nextProps,nextState):将要更新组件时触发的函数

shouldComponentUpdate生命周期钩子返回true以后,组件进入重新渲染的流程,进入componentWillUpdate,这里同样可以拿到nextProps和nextState。

【9】componentDidUpdate(prevProps,prevState):组件更新完成时触发的函数

这是组件更新之后触发的生命周期钩子,组件更新完毕后,react只会在第一次初始化成功会进入componentDidmount,之后每次重新渲染后都会进入这个生命周期,这里可以拿到prevProps和prevState,即更新前的props和state。

【10】static getDerivedStateFromProps(nextProps,prevState):静态方法生命周期钩子

getDerivedStateFromProps 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。为什么getDerivedStateFromProps生命周期钩子要设计成静态方法呢?因为这样开发者就访问不到this也就是实例了,也就不能在里面调用实例方法或者setsState了,用一个静态函数getDerivedStateFromProps来取代被废弃的其他几个生命周期函数,就是强制开发者在render之前只做无副作用的操作,而且能做的操作局限在根据props和state决定新的state 而已。

【11】 getSnapshotBeforeUpdate(prevProps,prevState):保存状态快照

它是用来代替componentWillUpdate生命周期钩子函数的,常见的 componentWillUpdate 的用例是在组件更新前,读取当前某个 DOM 元素的状态,并在 componentDidUpdate 中进行相应的处理。

这两者的区别在于:

  1. 在 React 开启异步渲染模式后,在 render 阶段读取到的 DOM 元素状态并不总是和 commit 阶段相同,这就导致在
    componentDidUpdate 中使用 componentWillUpdate 中读取到的 DOM 元素状态是不安全的,因为这时的值很有可能已经失效了。
  2. getSnapshotBeforeUpdate 会在最终的 render 之前被调用,也就是说在 getSnapshotBeforeUpdate 中读取到的 DOM 元素状态是可以保证与 componentDidUpdate 中一致的。此生命周期返回的任何值都将作为参数传递给componentDidUpdate()。

四、实例

【1】挂载阶段

创建一个子组件,代码如下,在父组件引入渲染即可

import React ,{Component} from 'react'class Child extends Component{// 初始化constructor(props){console.log('01构造函数')       super(props)this.state={}}// 组件将要挂载时候触发的生命周期函数componentWillMount(){console.log('02组件将要挂载')}// 组件挂载完成时候触发的生命周期函数componentDidMount(){console.log('04组件挂载完成')}// 组件挂载时触发的生命周期函数render(){console.log('03数据渲染render')return(<div>Child组件</div>) }
}
export default Child

控制台打印结果顺序如下:

01构造函数
02组件将要挂载
03数据渲染render
04组件挂载完成

【2】更新阶段

数据更新的话第一步是shouldComponentUpdate确认是否要更新数据,当这个函数返回的是true的时候才会进行更新,并且这个函数可以声明两个参数nextProps和nextState,nextProps是父组件传给子组件的值,nextState是数据更新之后值,这两个值可以在这个函数中获取到。第二步当确认更新数据之后componentWillUpdate将要更新数据,第三步依旧是render,数据发生改变render重新进行了渲染。第四步是componentDidUpdate数据更新完成。

import React, { Component } from 'react'class Child extends Component {constructor(props) {super(props)this.state = {msg: '我是一个msg数据'}}//是否要更新数据,如果返回true才会更新数据shouldComponentUpdate(nextProps, nextState) {console.log('01是否要更新数据')return true;               //返回true,确认更新}//将要更新数据的时候触发的生命周期函数componentWillUpdate() {console.log('02组件将要更新')}//更新完成时触发的生命周期函数componentDidUpdate() {console.log('04组件更新完成')}//更新数据方法setMsg() {this.setState({msg: '我是改变后的msg数据'})}render() {console.log('03数据渲染render')return (<div>{this.state.msg}<button onClick={() => this.setMsg()}>点我更新msg的数据</button></div>)}
}
export default Child

点击按钮更新数据,控制台打印结果顺序如下:

01是否要更新数据
02组件将要挂载
03数据渲染render
04组件更新完成

五、参考

React官网: https://zh-hans.reactjs.org/

文章每周持续更新,可以微信搜索「 前端大集锦 」第一时间阅读,回复【视频】【书籍】领取200G视频资料和30本PDF书籍资料

React生命周期钩子函数相关推荐

  1. React 生命周期 钩子函数

    React15 挂载过程 // 完成了React数据的初始化. props.state constructor() // 组件已经完成初始化数据,但是还未渲染DOM时执行的逻辑 componentWi ...

  2. reactjs组件生命周期:componentWillReceiveProps及新旧版本生命周期钩子函数对比

    reactjs组件生命周期:componentWillReceiveProps及新旧版本生命周期钩子函数对比

  3. 详解Vue八大生命周期钩子函数

    摘要:Vue为生命周期中的每个状态都设置了钩子函数(监听函数) .每当Vue实例处于不同的生命周期时,对应的函数就会被触发调用. 本文分享自华为云社区<一文带你弄懂Vue八大生命周期钩子函数&g ...

  4. 不来看看这些 VUE 的生命周期钩子函数? | 原力计划

    作者 | huangfuyk 责编 | 王晓曼 出品 | CSDN 博客 VUE的生命周期钩子函数:就是指在一个组件从创建到销毁的过程自动执行的函数,包含组件的变化.可以分为:创建.挂载.更新.销毁四 ...

  5. uni-app中的生命周期钩子函数

    1.应用级(App)生命周期钩子函数--App.vue -- 类似于小程序 onLaunch:应用启动了,每次运行只能执行一次 onShow:应用再次显示出来,每次显示出来都会调用 onHide:应用 ...

  6. 实战 Vue 之生命周期钩子函数执行顺序

    实战 Vue 之生命周期钩子函数执行顺序 生命周期钩子函数 父组件与子组件执行顺序 生命周期钩子函数 beforeCreate:实例刚被创建出来,data 数据和 methods 方法还未被初始化,不 ...

  7. vue的组件/data的参数/组件传值/插槽/侦听器/生命周期钩子函数

    目录 组件结构 组件的命名规则: 组件的data参数 <font color='red'> 组件的父子传值prop(通信) <font color='red'>组件的子--&g ...

  8. Vue3 生命周期钩子函数

    一.Vue3生命周期钩子 setup() : 开始创建组件之前,在 beforeCreate 和 created 之前执行,创建的是 data 和 method onBeforeMount() : 组 ...

  9. Vue的生命周期钩子函数介绍

    感谢内容提供者:金牛区吴迪软件开发工作室 Vue的生命周期钩子函数介绍 vue生命周期共分为四个阶段 一:实例创建 二:DOM渲染 三:数据更新 四:销毁实例 共有八个基本钩子函数 1.beforeC ...

  10. vue生命周期钩子函数的正确使用方式

    对于vue生命周期我们还是要先了解清楚,因为不同的生命期用不同的钩子函数,先上图: 遇到的一个问题 在我的项目中,常用的生命周期钩子函数一直都是mounted,对于大部分情况,都是屡试不爽.捷报频传~ ...

最新文章

  1. pytorch 损失函数总结
  2. [笔记]modelsim前仿后仿各种问题
  3. 情感分析基于词典(算例代码)
  4. 继承(父类,子类的继承方式,成员变量、静态变量的引用方法)
  5. Golang——枚举(iota)的使用
  6. 360浏览器清除缓存_微信缓存清理教程
  7. XFS:大数据环境下Linux文件系统的未来?
  8. 知识点学习之LPCNet
  9. 输入年份和月份输出该月有多少天python_题目内容:读入一个年份和月份,输出该月有多少天(考虑闰年),用s? 爱问知识人...
  10. [转]计算机经典书籍
  11. ubuntu安装nvidia显卡驱动黑屏nvidia-smi黑屏-显卡故障
  12. Linux原理与应用A卷广东科技,Linux操作系统应用选择题附答案(广东开放大学)...
  13. #217-[哈希]好人卡
  14. 申请软件著作权的流程有哪些?让专业人士带你了解
  15. apache的HttpClient的默认重试机制
  16. ICPC——2021台湾站(A B C D E J)
  17. 《炬丰科技-半导体工艺》IC制造化学清洗过程中硅上重金属污染的表面光电压监测
  18. 什么是STW以及CMS和G1优缺点?
  19. 嵌入式 Linux 开发工具篇问题整理//C语言测试(杨辉三角、递归调用实现阶乘、计算器、统计字符串出现次数)//2018.07.12.//
  20. Python生成密码字典教程

热门文章

  1. Python网站服务器搭建,python 最快速搭建一个网站
  2. 手机市场的竞争,用户价值才是硬道理
  3. 裁判文书网爬虫(2019.5.15更新)
  4. iqooneo5桌面原子组件教程分享
  5. jsonp跨域的原理
  6. 蒟蒻的做题录(时间)
  7. 小觅双目摄像头标准版视觉惯性 SLAM DEMO
  8. Java微信授权登陆
  9. 【软件开发规范一】《Java开发规范》
  10. OpenCV中出现“Microsoft C++ 异常: cv::Exception,位于内存位置 0x0000005C8ECFFA80 处。”的异常...