React生命周期总结v16+和v16-

news2024/11/19 11:26:23

React的生命周期

生命周期就函数就是指在某一个时间刻会自动调用执行的函数,React生命周期分为三个阶段

挂载:组件被创建并插入真实dom
渲染(更新):组建的props或state发生变化时触发的组件更新
卸载:组件被从DOM中移除

生命周期有两个版本,react16.3版本引入了新版本生命周期的方法【new life cycle】,react16.3之前,react使用的都是旧版本的生命周期【old life cycle】

old life cycle

react生命周期

new life cycle

在这里插入图片描述

挂载(Mounting):

constructor

constructor 只会在组件初始化的时候触发一次
组件的构造函数,第一个被执行,若没有显式定义它,会有一个默认的构造函数,但是若显式定义了构造函数,我们必须在构造函数中执行
super(props),否则无法在构造函数中拿到this。如果不初始化 state 或不进行方法绑定,则不需要为 React
组件实现构造函数Constructor。 constructor中通常只做两件事:【初始化组件state,给事件处理方法绑定this】

constructor(props){
        // 要在构造函数中调用 setState,可以直接给 state 设置初始值
        super(props);
        this.state={
            count: 0,
            inputValue:"",
        },
        this.handleClick = this.handleClick.bind(this)
    }

getDerivedStateFromProps:

该函数会在组件化实例化后和重新渲染前调用(生成 VirtualDOM 之后,实际 DOM 挂载之前)
这是个静态方法,所以不能在这个函数里使用,this,有两个参数 props 和 state,分别指接收到的新参数和当前组件的 state对象,这个函数会返回一个对象用来更新当前的 ,state 对象,如果不需要更新可以返回 null。
无论是父组件的更新、props的变化或通过 setState 更新组件内部的 State,它都会被调用。
该生命周期函数必须有返回值,返回一个对象来更新 State,若返回 null 表明新 props 不更新 state。新的生命周期加了新特性,当组件实例化时,该方法替代了componentWillMount,而当接收新的 props 时,该方法替代了 componentWillReceiveProps 和componentWillUpdate。
适用于表单获取默认值。
static getDerivedStateFromProps(props, state)

import React, { Component } from 'react';  //(0)【引入组件第一种写法】
import '../App.css';
    class Homes extends Component {         //(0-1)对应第一种引入react引入方法类写法
        //(1)接下来两行为固定写法
        constructor(props) {
            // 要在构造函数中调用 setState,可以直接给 state 设置初始值
            super(props);
            this.state = {
                count: 0,
                inputValue: "",
            },
                this.handleClick = this.handleClick.bind(this)
        }
        handleClick = () => {
            this.setState({
                count: this.state.count + 1
            })
        }
        static getDerivedStateFromProps(props, state) {
            if (props.count !== state.count) {
                return {
                    count: props.count
                }
            }
            return null
        }
      render() {
        return (
          <div>
            <h1 onClick={this.handleClick}>Hello, world!{this.state.count}</h1>
          </div>
        )
      }
    };
export default Homes;

现在可以显式传入 counter ,但是这里有个问题,如果想要通过点击实现 state.counter 的增加,但这时会发现值不会发生任何变化,一直保持 props 传进来的值。这是由于在 React 16.4^ 的版本中 setState 和 forceUpdate 也会触发这个生命周期,所以当组件内部 state 变化后,就会重新走这个方法,同时会把 state 值赋值为 props 的值。因此需要多加一个字段来记录之前的 props 值,这样就会解决上述问题。

import React, { Component } from 'react';  //(0)【引入组件第一种写法】
import '../App.css';
class Homes extends Component {         //(0-1)对应第一种引入react引入方法类写法
    //(1)接下来两行为固定写法
      constructor(props) {
            // 要在构造函数中调用 setState,可以直接给 state 设置初始值
            super(props);
            this.state = {
               count: 0,
 preCount:0,
                inputValue: "",
            },
                this.handleClick = this.handleClick.bind(this)
        }
        handleClick = () => {
            this.setState({
                count: this.state.count + 1
            })
        }
        static getDerivedStateFromProps(props, preCount) {
            if (props.count !== state.preCount) {
                return {
                    count: props.count,
      preCount:props.counter
                }
            }
            return null
        }
      render() {
        return (
          <div>
            <h1 onClick={this.handleClick}>Hello, world!{this.state.count}</h1>
          </div>
        )
      }
    };
export default Homes;

render:

组件初始化,页面state或props发生变化时执行。 render是React 中最核心的方法,一个组件中必须要有这个方法,它会根据状态
state 和属性 props 渲染组件。这个函数只做一件事,就是返回需要渲染的内容,所以不要在这个函数内做其他业务逻辑,通常调用该方法会返回以下类型中一个:
       a.React元素这里包括原生的DOM 以及React 组件。
       b.数组和Fragment(片段):可以返回多个元素。
       c.Portals(插槽):可以将子元素渲染到不同的DOM中。
       d.字符串和数字:被渲染成DOM中的text节点。
       e.布尔值或者null:不渲染任何内容。

componentDidMount :

在组件挂载完成之后 (插入DOM树后) 立即调用。
componentDidMount()会在组件挂载后(插入 DOM 树中)立即调用。
该阶段通常执行依赖于DOM的操作,发送网络请求,添加订阅消息(会在componentWillUnmount取消订阅),添加事件监听,如果使用了Redux之类的数据管理工具也能触发action处理数据变化逻辑。此钩子函数中允许使用setState改变组件内的State。
注意:该生命周期函数在进行服务器端渲染时候不会触发(仅客户端有效)。如果在componentDidMount中调用setState,就会触发一次额外的渲染,多调用了一次render函数,由于他是在浏览器刷新屏幕前执行的,所以用户对此没有感知的,但是应当避免这样使用,这样带来的一定的性能问题,精良在constructor中初始化state对象。

class App extends React.Component  {
  constructor(props) {
    super(props)
    this.state = {
      count: 0
    }
  }
  componentDidMount () {
    this.setState({
      count: 1
    })
  }
  render ()  {
    return (
      <div className="count">
        counter值: { this.state.count }
      </div>
    )
  }
}

更新(Updation):

setState、useState、props变化、forceUpdate会触发组件的更新,但是组件是否从新渲染取决于shouldComponentUpdate。

shouldComponentUpdate:

函数会在组件更新之前,自动被执行。它要求返回一个布尔类型的结果,必须有返回值。返回true时组件更新,返回false则不更新。
当props或者state发生变化,在重新渲染执行之前,第一个是即将更新的props值,第二个是即将更新后的state值,可以根据更新前后的props或者state来比较加一些限制条件,决定是否更新进行性能优化,当该方法返回的布尔值false告知react无需重新渲染时,render,UNSAFE_componentWillUpdate和conponentDidUpdate等生命周期钩子函数都不会被触发。
    a.  此钩子函数在初始化渲染和使用forceUpdate方法的情况下不会被触发, 使用forceUpdate会强制更新
    b.  禁止在此函数中使用setState方法,会导致循环调用

shouldComponentUpdate(){
    console.log('shouldComponentUpdate---组件发生改变前执行')
    return true
}

现在就可以在控制台,console里看到结果了,并且结果是每次文本框发生改变时都会随着改变。如果你返回了
false,这组件就不会进行更新了。 简单点说,就是返回true,就同意组件更新;返回false,就反对组件更新。

getSnapshotBeforeUpdate (新):

保存状态快照。该生命周期函数会在组件即将挂载时触发,它的触发在 render 渲染函数之后。 这个方法在render之后,componentDidUpdate之前调用,有两个参数prevProps和prevState,标识更新之前的props和state,这个函数必须要和componentDidUpdate一起使用,并且要有一个返回值,默认是null,这个返回值座位第三个参数传递给componentDidUpdate。该生命周期函数执行完毕后就会立即触发componentDidUpdate 生命周期钩子。

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

该生命周期函数能让你捕获某些从 DOM 中才能获取的(可能会变更的例如滚动位置),此生命周期返回的任何值都会作为第三个参数传递给 componentDidUpdate()。如不需要传递任何值,那么请返回 null。

componentDidUpdate:

在组件更新之后执行,它是组件更新的最后一个环。 该方法有三个参数【componentDidUpdate(prevProps,prevState, snapshot){}】
    a.  prevProps: 更新前的props
    b.  prevState: 更新前的state
    c.  snapshot: getSnapshotBeforeUpdate()生命周期的返回值
组件每次重新渲染后会触发 componentDidUpdate 但是只有在组件首次渲染(即初始化)时触发的是componentDidMount钩子函数,初始化渲染后componentDidMount 不会再被触发。 操作 DOM;发送网络请求。 在componentDidUpdate 生命周期函数中调用 setState 方法时,确实需要加上条件判断,以避免死循环的发生。通过判断 prevProps、prevState 和 this.state 之间的数据变化,来判断是否执行相关的 state 变更逻辑,这使得尽管在 componentDidUpdate 中调用了 setState 进行再更新,如果条件不成立state就不会进行更新,从而避免了死循环的发生。

	componentDidUpdate(prevProps){
		if (this.props.id !== prevProps.id){
			this.fetchData(this.props.id);
		}
	}

卸载(Unmounting):

componentWillUnmount:

它是在组件去除时执行。在组件卸载和销毁之前触发。可以利用这个生命周期方法进行事件的解绑。 用于移除事件监听器;取消网络请求;取消定时器;解绑DOM 事件。 在该方法中调用 setState 不会触发 render,因为所有的更新队列,更新状态都被重置为null。这个生命周期在一个组件被卸载和销毁之前被调用,因此不应该再这个方法中使用setState,因为组件一旦被卸载,就不会再装载,也就不会重新渲染。
新版本的生命周期就开始废弃了componentWillMount、componentWillReceiveProps、componentWillUpdate的三个钩子,并为这几个钩子提供了别名

  • UNSAFE_componentWillMount:当组件被渲染出来之前
  • UNSAFE_componentWillReceiveProps:当组件收到新的props之前
  • UNSAFE_componentWillUpdate:组件更新前

父子组件加载顺序

父子组件初次加载会在子组件挂挂载完成后继续父组件的挂载

  • Parent 组件: constructor()
  • Parent 组件: getDerivedStateFromProps()
  • Parent 组件: render()
  • Child 组件: constructor()
  • Child 组件: getDerivedStateFromProps()
  • Child 组件: render()
  • Child 组件: componentDidMount()
  • Parent 组件: componentDidMount()

当执行render子组件的时候,才会进入子组件的生命周期,子组件的周期结束后,再回到上级的周期。 改变子组件自身状态

Child 组件: getDerivedStateFromProps()

  • Child 组件: shouldComponentUpdate()
  • Child 组件: render()
  • Child 组件: getSnapshotBeforeUpdate()
  • Child 组件: componentDidUpdate()

修改父组件传入给子组件的 props 当父组件修改传递的 props 值时,会触发父子组件的更新

Parent 组件: getDerivedStateFromProps()

  • Parent 组件: shouldComponentUpdate()
  • Parent 组件: render()
  • Child 组件: getDerivedStateFromProps()
  • Child 组件: shouldComponentUpdate()
  • Child 组件: render()
  • Child 组件: getSnapshotBeforeUpdate()
  • Parent 组件: getSnapshotBeforeUpdate()
  • Child 组件: componentDidUpdate()
  • Parent 组件: componentDidUpdate()

只修改父组件的值 当父组件的值被修改时,会触发父组件的 render() 方法重新渲染,并递归地 r-render 子组件。这个过程中,会依次触发所有子组件的生命周期方法:

  • Parent 组件: getDerivedStateFromProps()
  • Parent 组件: shouldComponentUpdate()
  • Parent 组件: render()
  • Child 组件: getDerivedStateFromProps()
  • Child 组件: shouldComponentUpdate()
  • Child 组件: render()
  • Child 组件: getSnapshotBeforeUpdate()
  • Parent 组件: getSnapshotBeforeUpdate()
  • Child 组件: componentDidUpdate()
  • Parent 组件: componentDidUpdate()

所以不管父组件有没有把数据传递给子组件,只要父组件
setState,都会走一遍子组件的更新周期。而且子组件被动更新会比主动更新所执行的流程多出来一个
componentWillReceiveProps 方法。

子组件修改自身state

当我们修改子组件中的数据时,只有子组件会经历更新生命周期,而父组件不会。

  • 子组件 getDerivedStateFromProps
  • 子组件 shouldComponentUpdate
  • 子组件 render
  • 子组件 getSnapShotBeforeUpdate
  • 子组件 componentDidUpdate

卸载子组件,触发父组件的重新渲染、子组件销毁

  • Parent 组件: getDerivedStateFromProps()
  • Parent 组件: shouldComponentUpdate()
  • Parent 组件: render()
  • Parent 组件: getSnapshotBeforeUpdate()
  • Child 组件: componentWillUnmount()
  • Parent 组件: componentDidUpdate()

当子组件自身状态改变时,不会对父组件产生副作用的情况下,父组件不会进行更新,即不会触发父组件的生命周期,当父组件中状态发生变化(包括子组件的挂载以及卸载)时,会触发自身对应的生命周期以及子组件的更新。

完结~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1105690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

macOS Sonoma 14.1RC(23B73)发布

黑果魏叔10 月 18 日消息&#xff0c;苹果今日向 Mac 电脑用户推送了 macOS 14.1 RC更新&#xff08;内部版本号&#xff1a;23B73&#xff09;&#xff0c;本次更新距离上次发布隔了 7 天。 macOS Sonoma 14.1RC&#xff08;23B73&#xff09;的更新内容主要包括以下方面&…

2023年煤气证模拟考试题库及煤气理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年煤气证模拟考试题库及煤气理论考试试题是由安全生产模拟考试一点通提供&#xff0c;煤气证模拟考试题库是根据煤气最新版教材&#xff0c;煤气大纲整理而成&#xff08;含2023年煤气证模拟考试题库及煤气理论考…

交银国际:拼多多财报预测:主站盈利提升有望带动业绩超预期

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;交银国际今日发布关于拼多多第三季度财报预测&#xff1a;主站盈利提升有望带动业绩超预期的研报。交银国际主要观点如下&#xff1a; 预计拼多多(PDD)第三季度业绩将好于市场预期&#xff1a;我们…

JWT越权访问漏洞

JWT越权访问漏洞 文章目录 JWT越权访问漏洞原文参考 :[xiu](http://www.xiusafe.com/2023/02/08/JWT/)1 靶场搭建:2 JWT的头部组成2.1 头部2.1.1 alg:2.1.2 type: 2.2 payload2.3 签名 3 漏洞复现3.1 攻击点token&#xff08;第三关&#xff09;3.2 对token值base64的加密码方式…

深度学习——深度卷积神经网络(AlexNet)

深度学习——深度卷积神经网络&#xff08;AlexNet) 文章目录 前言一、学习表征二、AlexNet实现2.1. 模型设计2.2. 激活函数2.3. 容量控制与预处理2.4. 训练模型 总结 前言 在前面学习了卷积神经网络的基本原理&#xff0c;之后将继续学习现代卷积神经网络架构。而本章将学习其…

上网冲浪发现多处XSS

突然的发现 今天上网冲浪&#xff0c;突然想起来有一种神器&#xff0c;叫废话生成器&#xff0c;之前是在哪里下了个软件玩了一下&#xff0c;然后就给删除了&#xff0c;因为我觉得这个软件不过就是调用了一个web接口实现的&#xff0c;一个网页能解决的事还要我下一个软件。…

PR2023中如何导入字幕

PR中如何导入字幕 方法一&#xff1a; 点开文本&#xff0c;字幕&#xff0c;新建字幕分段&#xff08;点击右上角…三个点&#xff09; 键入调整内容 方法二 点开基本图形&#xff0c;编辑&#xff0c;调整&#xff0c;拖动位置。

移动设备管理对企业IT 安全的增强

移动设备管理 &#xff08;MDM&#xff09; 是通过定义策略和部署安全控制&#xff08;如移动应用程序管理、移动内容管理和条件 Exchange 访问&#xff09;来管理移动设备的过程。 完整的MDM解决方案可以管理在Android&#xff0c;iOS&#xff0c;Windows&#xff0c;macOS&a…

23上半年下午题

针对哔哩哔哩视频做的笔记&#xff0c;源地址在此 点这里 第一大题题目 第一大题解答 前两题比较简单&#xff0c;按照说明仔细填写即可。 第三问可以从以下几个方面入手&#xff0c; 1、上下文数据流图和0层数据流图是否平衡相对应 2、一个加工至少有一个输入和输出流 3、…

灵沐V3.01微信资源类小程序源码-支持流量主

时隔几年&#xff0c;终于推出全新升级版的灵沐V3.01流量主变现小程序 该版本支持微信、QQ和抖音&#xff0c;经过全局的UI设计升级&#xff0c;保持了主打功能——资源下载激励视频变现的特点 此外&#xff0c;我们还新增了Doc文档模式&#xff0c;可适用于文章&#xff1b;…

Linux内核的.config 配置文件和defconfig 配置文件

Linux 内核可以通过输入“make menuconfig”来打开图形化配置界面&#xff0c;menuconfig 是一套图形化的配置工具 一、图形化界面的操作 menuconfig 图形化的配置工具需要 ncurses 库支持。ncurses 库提供了一系列的 API 函数供调用者生成基于文本的图形界面&#xff0c;因此…

数据保护双保险,一文读懂NVMe协议中的Get LBA Status功能

就在前不久&#xff0c;我们发布了全新一代PCIe 5.0企业级NVMe SSD——PBlaze7 7940。与上一代PCIe 4.0产品相比&#xff0c;其综合性能有着超过100%的提升&#xff0c;增添了很多新的功能以满足企业级客户多样化的产品需求。其中一项新的功能便是我们今天谈论的主角——Get LB…

Mysql中日期相关的函数

Mysql中日期相关的函数 时间戳转变成日期datetime格式的函数 FROM_UNIXTIME(时间戳)&#xff0c;如下图&#xff1a; 获取datetime类型的月份和年份的函数 month获取月份&#xff0c;如下图&#xff1a; year获取年份&#xff0c;如下图&#xff1a; 给特定日期加一个月…

2023年四川省安全员B证证模拟考试题库及四川省安全员B证理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年四川省安全员B证证模拟考试题库及四川省安全员B证理论考试试题是由安全生产模拟考试一点通提供&#xff0c;四川省安全员B证证模拟考试题库是根据四川省安全员B证最新版教材&#xff0c;四川省安全员B证大纲整理…

软件测试基础知识整理(详细版)

一、软件测试概述 1、软件缺陷 软件缺陷&#xff1a;又称之为“Bug”。即计算机软件或程序中存在的某种破坏正常运行能力的问题、错误&#xff0c;或者隐藏的功能缺陷。 缺陷的表现形式&#xff1a; 软件没有实现产品规格说明书所要求的功能模块&#xff1b; 软件中出现了产…

C++对象模型(16)-- 构造函数语义学:临时对象

临时对象是栈上的没有名字的对象&#xff0c;它在源码中是不可见的&#xff0c;是编译器偷偷摸摸在背后干的。 比如下面的代码就会产生临时对象&#xff1a; int i 1;// 这里的 i 会产生临时对象&#xff0c;这里的临时对象是在系统中产生&#xff0c;代码中看不见的 // 首先…

Deep Joint Demosaicking and Denoising

Abstract 去马赛克和去噪是数字成像流程的关键第一阶段&#xff0c;但它们也是一个严重不适定的问题&#xff0c;从单个噪声测量中推断出每个像素的三个颜色值。早期的方法依赖于手工制作的滤波器或先验&#xff0c;并且在硬情况下&#xff08;例如摩尔纹或薄边缘&#xff09;…

Bootstrap的导航栏设计相关知识

Bootstrap的导航栏设计相关知识 目录 01-基础知识02-最基本的导航栏设计例子03-带下拉菜单的导航04-在导航栏中添加表单元素05-固定导航栏的位置(如固定到顶部和底部)06-设计导航栏的颜色和文本颜色 01-基础知识 导航栏是网页设计中不可缺少的部分&#xff0c;它是整个网站的…

ABB变频器使用PROFINET IO通信模块时的激活方法

ABB变频器使用PROFINET IO通信模块时的激活方法 ABB传动通讯总线适配器的激活(ACS380): 首先,如下图所示,要采购并安装PROFINET IO总线通信模块(我这里支持3种通信协议,大家在实际使用时,用到哪种就购买哪种即可), 如下图所示,进入参数设置, 如下图所示,进入“完…

如何使用Python抓取PDF文件并自动下载到本地

目录 一、导入必要的库 二、发送HTTP请求并获取PDF文件内容 三、将PDF文件内容写入到本地文件中 四、完整代码示例 五、注意事项 六、错误处理和异常处理 七、进一步优化 总结 在Python中&#xff0c;抓取PDF文件并自动下载到本地需要使用几个不同的库。首先&#xff0…