9. React组件生命周期

2. React组件生命周期

  • 2.1. 认识生命周期
    • 2.1.1. 很多事物都有从创建到销毁的整个过程,这个过程称之为生命周期;
    • 2.1.2. React组件也有自己的生命周期,了解生命周期可以让我们在最合适的地方完成想要的功能
    • 2.1.3. 生命周期和生命周期函数的关系:
      • 2.1.3.1. 生命周期是一个抽象的概念,在生命周期的整个过程,分成了很多个阶段;
        • 比如挂载阶段(Mount), 组件第一次在DOM树中被渲染的过程;
        • 比如更新阶段(Update), 组件状态发生变化时,重新更新渲染的过程;
        • 比如卸载阶段(Unmount), 组件从DOM树中移除的过程;
      • 2.1.3.2. React内部为了告诉我们当前处于那些阶段,会对组件内部实现的某些函数进行回调,这些函数就是生命周期函数
        • 比如实现componentDidMount函数组件已经挂载到DOM上时,就会回调;
        • 比如实现componentDidUpdate函数组件已经更新时,就会回调;
        • 比如实现componentWillUnmount函数组件即将被移除时,就会回调;
        • 可以在这些回调函数中编写自己的逻辑代码,来完成自己的需求功能;
    • 2.1.4. React生命周期时,主要指的是类的生命周期,因为函数式组件是没有生命周期函数的(后面可以通过hooks来模拟一些生命周期的回调,写到hooks会在进行记录)
  • 2.2. 生命周期解析
    • 2.2.1. 先来了解下最基础、最常用的生命周期函数:compentDidMountcomponentDidUpdatecomponentWillUnmount函数

    • 2.2.2. 生命周期函数如图:官网图谱地址
      在这里插入图片描述
      在这里插入图片描述

    • 2.2.3. 挂载阶段:componentDidMount

        1. 在挂载时,首先会创建一个组件实例,在创建实例的过程中,就会执行类中constructor函数(每次引入使用组件时,创建的是ReactElement, 每次调用就创建一个组件实例, 每次创建实例时,就会先执行constructor函数)
        -> 类实例class Person {} ->const p1 = new Person() -> 类实例
        
        1. 紧接着调用类中的render方法
        1. 挂载完成后会调用的componentDidMount函数
        1. 如下图:
          在这里插入图片描述
        1. 示例代码如下:
        • HelloWorld.jsx
          //import React from 'react';class HelloWorld extends React.Component {// 1.构造方法:constructorconstructor () {console.log('HelloWorld constructor')super();this.state = {message: 'Hello World'}}// 2.执行render方法render () {console.log('HelloWorld render')return (<div><h2>Hello World</h2><p>Hello World是程序员的第一个代码</p></div>)}// 3.组件被渲染到DOM:被挂载到DOM上componentDidMount () {console.log('HelloWorld componentDidMount')}}export default HelloWorld;
        
        • App.jsx
          import React from "react";import HelloWorld from "./HelloWorld";class App extends React.Component {render () {return (<div>哈哈哈哈{/* 组件每引用一次,就创建一个实例,每创建一次组件实例,就会先执行constructor函数 */}<HelloWorld /><HelloWorld />{/* <HelloWorld /><HelloWorld /> */}</div>)}}export default App;
        
    • 2.2.4. 更新阶段:componentDidUpdate

        1. 当数据发生更新时,执行setState方法
        1. 执行setState方法后,重新渲染页面, 重新执行render方法,它会根据最新修改之后的message,重新生成一个新的树,然后在进行diff算法,然后决定要更新那部分
        1. react会更新dom和refs,并调用componentDidUpdate方法
        1. 如下图:
          在这里插入图片描述
        • 关键代码如下;
             // 4.组件的DOM被更新完成:DOM发生更新componentDidUpdate () {/***    * - 1. 当数据发生更新时,执行setState方法* - 2. 执行setState方法后,重新渲染页面, 重新执行render方法,它会根据最新修改之后的message,重新生成一个新的树,然后在进行diff算法,然后决定要更新那部分* - 3. react会更新dom和refs,并调用componentDidUpdate方法* * * */console.log('HelloWorld componentDidUpdate')}
          
        • 详细代码如下:
            import React from 'react';class HelloWorld extends React.Component {// 1.构造方法:constructorconstructor () {console.log('HelloWorld constructor')super();this.state = {message: 'Hello World'}}changeText () {this.setState({ message: '你好啊 李银河' })}// 2.执行render方法render () {const { message } = this.stateconsole.log('HelloWorld render')return (<div><h2>{message}</h2><button onClick={e => this.changeText()}>修改文本</button><p>{message}是程序员的第一个代码</p></div>)}// 3.组件被渲染到DOM:被挂载到DOM上componentDidMount () {/***    * - 1. 在挂载时,首先会创建一个组件实例,在创建实例的过程中,就会执行类中`constructor函数`(每次引入使用组件时,创建的是ReactElement, 每次调用就创建一个组件实例, 每次创建实例时,就会先执行constructor函数)* - 2. 紧接着调用类中的`render方法`* - 3. 挂载完成后会调用的`componentDidMount函数`* * * */ console.log('HelloWorld componentDidMount')}// 4.组件的DOM被更新完成:DOM发生更新componentDidUpdate () {/***    * - 1. 当数据发生更新时,执行setState方法* - 2. 执行setState方法后,重新渲染页面, 重新执行render方法,它会根据最新修改之后的message,重新生成一个新的树,然后在进行diff算法,然后决定要更新那部分* - 3. react会更新dom和refs,并调用componentDidUpdate方法* * * */console.log('HelloWorld componentDidUpdate')}}export default HelloWorld;
          
    • 2.2.5. 卸载阶段:componentWillUnmount

        1. 当组件从 DOM 中移除时,会调用 componentWillUnmount() 方法。
        1. 如下图:
          在这里插入图片描述
        1. 示例代码:
        • 关键代码:
          // 5.组件从DOM中卸载掉:从DOM移除掉componentWillUnmount () {console.log('HelloWorld componentWillUnmount')}
        
        1. 完整代码:
        • HelloWorld.jsx
          import React from 'react';class HelloWorld extends React.Component {// 1.构造方法:constructorconstructor () {console.log('HelloWorld constructor')super();this.state = {message: 'Hello World'}}changeText () {this.setState({ message: '你好啊 李银河' })}// 2.执行render方法render () {const { message } = this.stateconsole.log('HelloWorld render')return (<div><h2>{message}</h2><p>{message}是程序员的第一个代码</p><button onClick={e => this.changeText()}>修改文本</button></div>)}// 3.组件被渲染到DOM:被挂载到DOM上componentDidMount () {/***    * - 1. 在挂载时,首先会创建一个组件实例,在创建实例的过程中,就会执行类中`constructor函数`(每次引入使用组件时,创建的是ReactElement, 每次调用就创建一个组件实例, 每次创建实例时,就会先执行constructor函数)* - 2. 紧接着调用类中的`render方法`* - 3. 挂载完成后会调用的`componentDidMount函数`* * * */ console.log('HelloWorld componentDidMount')}// 4.组件的DOM被更新完成:DOM发生更新componentDidUpdate () {/***    * - 1. 当数据发生更新时,执行setState方法* - 2. 执行setState方法后,重新渲染页面, 重新执行render方法,它会根据最新修改之后的message,重新生成一个新的树,然后在进行diff算法,然后决定要更新那部分* - 3. react会更新dom和refs,并调用componentDidUpdate方法* * * */console.log('HelloWorld componentDidUpdate')}// 5.组件从DOM中卸载掉:从DOM移除掉componentWillUnmount () {console.log('HelloWorld componentWillUnmount')}}export default HelloWorld;
        
        • App.jsx
        import React from "react";
        import HelloWorld from "./HelloWorld";class App extends React.Component {constructor () {super();this.state = {isSHowHw: true}}switchShowHw () {this.setState ({ isSHowHw: !this.state.isSHowHw })}render () {const { isSHowHw } = this.state;return (<div>哈哈哈哈{/* 组件每引用一次,就创建一个实例,每创建一次组件实例,就会先执行constructor函数 */}<button onClick={ e => this.switchShowHw() }>切换</button>{ isSHowHw && <HelloWorld />}</div>) }
        }export default App;
        
    • 2.2.6. 开发中常用的是:constructor()、render()、componentDidMount()、componentWillUnmount()

  • 2.3. 生命周期函数
    • 2.3.1. constructor
        1. 如果不初始化state或不进行方法绑定,则不需要为React组件实现构造函数。
        1. constructor中通常只做两件事:
        • 通过给this.state赋值对戏那个初始化内部的state;
        • 为事件绑定实例(this);
    • 2.3.2 componentDidMount
        1. componentDidMount()会在组件挂载之后(插入DOM树中)立即调用
        1. componentDidMount中通过进行那些操作?
        • 2.1. 依赖于DOM的操作可以在这里进行;
        • 2.2. 再次是发送网络请求最好的地方(官方建议)
        • 2.3. 可以在此处添加一些订阅(在componentWillUnmount中取消订阅,不然会内存泄漏)
    • 2.3.3 componentDidUpdate
        1. componentDidUpdate()会在组件更新之后立即调用, 首次渲染不会执行此方法;
        • 当组件更新后,可以在此处对DOM进行操作;
        • 如果对更新前后的props进行了比较,也可以选择在此处进行网络请求(例如:当props未发生变化时,则不会执行网络请求)
    • 2.3.4 componentWillUnmount
        1. componentWillUnmount()会在组件卸载以及销毁之前直接调用。
        • 在此方法中执行必要的清理操作;
        • 例如:清楚timer, 取消网络请求或清除在componentDidMount中创建的订阅等;
  • 2.4. 不常用的生命周期函数
    • 2.4.1. 不常用的生命周期如下图:
      在这里插入图片描述

    在这里插入图片描述

    • 2.4.2. 不常用生命周期多出来这些方法:getDerivedStateFromProps()、shouldComponentUpdate()、getSnapshotBeforeUpdate()

    • 2.4.3. getDerivedStateFromProps()

        1. getDerivedStateFromProps():在更新或者第一次挂载时,如果state里面的数据需要依赖Props, 可以在这个回调函数里完成,这个函数用的非常少
        1. getDerivedStateFromProps(): state的值在任何使用时候依赖于props时候用,该方法返回一个对象来更新state
    • 2.4.4. shouldComponentUpdate ()

        1. shouldComponentUpdate(): 该生命周期函数很常用,等记录到性能优化时再详细记录;
        1. 组件是否需要更新(shouldComponentUpdate翻译:组件要不要更新),返回true或者false,默认是true。
        1. 当通过setState去更新数据的时候,render函数一般会直接执行,重新渲染,如果在shouldComponentUpdate生命周期里面返回false,render()不会执行,组件不会重新渲染。
        1. 某些情况下返回false,可以提高性能
    • 2.4.5. getSnapshotBeforeUpdate()

        1. getSnapshotBeforeUpdate():React更新DOM之前回调的一个函数,可以获取DOM更新前的一些信息(例如:滚动位置)
        1. (Snapshot:快照)在组件更新之前,获取快照,保存一些数据,返回值会作为参数传递给componentDidUpdate()方法。
      • 在这里插入图片描述
    • 2.4.6. 更详细的生命周期相关的内容,可以参考官网:官网

    • 2.4.7. 不常用生命周期函数代码示例如下:

      • 关键代码:
        // 6.不常用的生命周期补充shouldComponentUpdate () {// 是否需要重新更新,默认为true,重新更新render函数,重新渲染return true}getSnapshotBeforeUpdate () {console.log('getSnapshotBeforeUpdate')return {scrollPosition: 1000}}
      
      • 完整代码:
        import React from 'react';class HelloWorld extends React.Component {// 1.构造方法:constructorconstructor () {console.log('HelloWorld constructor')super();this.state = {message: 'Hello World'}}changeText () {this.setState({ message: '你好啊 李银河' })}// 2.执行render方法render () {const { message } = this.stateconsole.log('HelloWorld render')return (<div><h2>{message}</h2><p>{message}是程序员的第一个代码</p><button onClick={e => this.changeText()}>修改文本</button></div>)}// 3.组件被渲染到DOM:被挂载到DOM上componentDidMount () {/***    * - 1. 在挂载时,首先会创建一个组件实例,在创建实例的过程中,就会执行类中`constructor函数`(每次引入使用组件时,创建的是ReactElement, 每次调用就创建一个组件实例, 每次创建实例时,就会先执行constructor函数)* - 2. 紧接着调用类中的`render方法`* - 3. 挂载完成后会调用的`componentDidMount函数`* * * */ console.log('HelloWorld componentDidMount')}// 4.组件的DOM被更新完成:DOM发生更新componentDidUpdate (prevProps, prevState, snapshot) {/***    * - 1. 当数据发生更新时,执行setState方法* - 2. 执行setState方法后,重新渲染页面, 重新执行render方法,它会根据最新修改之后的message,重新生成一个新的树,然后在进行diff算法,然后决定要更新那部分* - 3. react会更新dom和refs,并调用componentDidUpdate方法* * * */    console.log('HelloWorld componentDidUpdate: ', prevProps, prevState, snapshot)}// 5.组件从DOM中卸载掉:从DOM移除掉componentWillUnmount () {console.log('HelloWorld componentWillUnmount')}// 6.不常用的生命周期补充shouldComponentUpdate () {// 是否需要重新更新,默认为true,重新更新render函数,重新渲染, 返回false, 不执行render,不重新渲染界面return true}getSnapshotBeforeUpdate () {console.log('getSnapshotBeforeUpdate')return {scrollPosition: 1000}}}export default HelloWorld;
      

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

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

相关文章

【单板硬件开发】关于复位电路的理解

阅读紫光同创供应商提供的FPGA单板硬件开发手册&#xff0c;发现复位电路他们家解释的很通俗易懂&#xff0c;所以分享一下。如下图&#xff0c;RST_N 是低有效的异步全芯片复位信号&#xff0c;一般外部连接电路有 3 种形式如图 3–2&#xff0c;可根据实际需要选择合适的电路…

《Unity Shader入门精要》学习笔记一

1、本书的源代码 https://github.com/candycat1992/Unity_Shaders_Book 2、第1章 Shader是面向GPU的工作方式 3、第2章 渲染流水线 Shader&#xff1a;着色器 渲染流水线&#xff1a;目标是渲染一张二维纹理&#xff0c;输入是一个虚拟摄像机、一些光源、一些Shader以及纹…

从零到一:TCP 回声服务器与客户端的完整实现与原理详解

目录 一、TCP 通信的核心逻辑 二、TCP 服务器编程步骤 步骤 1&#xff1a;创建监听 Socket 步骤 2&#xff1a;绑定地址与端口&#xff08;bind&#xff09; 步骤 3&#xff1a;设置监听状态&#xff08;listen&#xff09; 步骤 4&#xff1a;接收客户端连接&#xff08…

MyBatis-Plus核心内容

MyBatis-Plus MyBatis-Plus 是一个基于 MyBatis的增强工具&#xff0c;旨在简化开发过程&#xff0c;减少重复代码。它在MyBatis的基础上增加了CRUD操作封装&#xff0c;条件构造器、代码生成器等功能。 一、核心特性与优势 1. 核心特性 无侵入&#xff1a;只做增强不做改变&am…

计算机网络摘星题库800题笔记 第4章 网络层

第4章 网络层4.1 网络层概述题组闯关1.在 Windows 的网络配置中&#xff0c;“默认网关” 一般被设置为 ( ) 的地址。 A. DNS 服务器 B. Web 服务器 C. 路由器 D. 交换机1.【参考答案】C 【解析】只有在计算机上正确安装网卡驱动程序和网络协议&#xff0c;并正确设置 IP 地址信…

非root用户在linux中配置zsh(已解决ncurses-devel报错)

Zsh&#xff08;Z Shell&#xff09;是一款功能强大的交互式 Unix shell&#xff0c;以其高度可定制性和丰富的功能著称&#xff0c;被视为 Bash 的增强替代品。它支持智能补全、主题美化、插件扩展&#xff08;如 Oh My Zsh 框架&#xff09;、自动纠错、全局别名等特性&#…

《Foundations and Recent Trends in Multimodal Mobile Agents: A Survey》论文精读笔记

论文链接&#xff1a;https://arxiv.org/pdf/2411.02006 摘要 文章首先介绍了核心组件&#xff0c;并探讨了移动基准和交互环境中的关键代表性作品&#xff0c;旨在全面理解研究重点及其局限性。 接着&#xff0c;将这些进展分为两种主要方法&#xff1a; 基于提示的方法&a…

npm安装时一直卡住的解决方法

npm install 卡住通常是由于网络问题或缓存问题导致的。以下是几种解决方法&#xff1a; 方法1&#xff1a;清理npm缓存 npm cache clean --force npm install方法2&#xff1a;删除node_modules和package-lock.json重新安装 rm -rf node_modules package-lock.json npm instal…

[密码学实战]使用Java生成国密SM2加密证书等(四十三)

[密码学实战]使用Java生成国密SM2加密证书等(四十三) 本文将详细介绍如何通过Java代码生成符合国密标准的SM2加密证书,包括密钥对生成、证书扩展属性配置、PEM格式保存等关键步骤。 一. 运行结果示例 二. 国密算法与加密证书 国密算法(SM系列)是中国自主研发的密码算法体…

从零开始之stm32之CAN通信

从小白的视角了解并实现简单的STM32F103的CAN通信&#xff0c;直接上手。一、CAN协议简介CAN总线上传输的信息称为报文&#xff0c;当总线空闲时任何连接的单元都可以开始发送新的报文&#xff0c;有5种类型的帧&#xff1a;数据帧、遥控帧、错误帧、过载帧、帧间隔。数据帧有两…

Java 课程,每天解读一个简单Java之利用条件运算符的嵌套来完成此题:学习成绩>=90分的同学用A表示,60-89分之间的用B表示, * 60分以下

package ytr250812;/*题目&#xff1a;利用条件运算符的嵌套来完成此题&#xff1a;学习成绩>90分的同学用A表示&#xff0c;60-89分之间的用B表示&#xff0c;* 60分以下*/import java.util.Scanner;public class GradeEvaluator {public static void main(String[] args) …

Word XML 批注范围克隆处理器

该类用于处理 Word 文档&#xff08;XML 结构&#xff09;中被批注标记的文本范围&#xff0c; 实现指定内容的深度克隆&#xff0c;并将其插入到目标节点之后。 适用于在生成或修改 .docx 文件时复制批注内容块。/*** Word XML 批注范围克隆处理器* * 该类用于处理 Word 文档&…

MQTT:Java集成MQTT

目录Git项目路径一、原生java架构1.1 导入POM文件1.2 编写测试用例二、SpringBoot集成MQTT2.1 导入POM文件2.2 在YML文件中增加配置2.3 新建Properties配置文件映射配置2.4 创建连接工厂2.5 增加入站规则配置2.6 增加出站规则配置2.7 创建消息发送网关2.8 测试消息发送2.9 项目…

day 16 stm32 IIC

1.IIC概述1基于对话的形式完成&#xff0c;不需要同时进行发送和接收所以删掉了一根数据线&#xff0c;变成半双工2为了安全起见添加了应答机制3可以接多个模块&#xff0c;且互不干扰4异步时序&#xff0c;要求严格&#xff0c;发送过程中不能暂停&#xff0c;所以需要同步时序…

AMD KFD的BO设计分析系列 0:开篇

开启我始终不敢碰的GPU存储系列&#xff0c;先上个图把核心关系表达下&#xff0c;以此纪念。注&#xff1a;图中kfdm_mm误写&#xff0c;应该为kfd_mm&#xff0c;不修改了&#xff0c;请大家不要介意。

EUDR的核心内容,EUDR认证的好处,EUDR意义

近年来&#xff0c;全球森林退化问题日益严峻&#xff0c;毁林行为不仅加剧气候变化&#xff0c;还威胁生物多样性和原住民权益。为应对这一挑战&#xff0c;欧盟于2023年6月正式实施《欧盟零毁林法案》&#xff08;EU Deforestation-free Regulation, EUDR&#xff09;&#x…

数据分析专栏记录之 -基础数学与统计知识

数据分析专栏记录之 -基础数学与统计知识&#xff1a; 1、描述性统计 均值 data_set [10, 20, 30, 40, 50] mean sum(data_set)/len(data_set)np 里面的函数&#xff0c;对二维进行操作时&#xff0c; 默认每一列 mean1 np.mean(data_set) print(mean, mean1)s 0 for i…

《星辰建造师:C++多重继承的奇幻史诗》

&#x1f30c;&#x1f525; 《星辰建造师&#xff1a;多重继承与this指针的终极史诗》 &#x1f525;&#x1f30c;—— 一场融合魔法、科技与哲学的C奇幻冒险&#x1f320;&#x1f30c; 序章&#xff1a;代码宇宙的诞生 &#x1f30c;&#x1f320;在无尽的代码维度中&#…

云计算-OpenStack 运维开发实战:从 Restful API 到 Python SDK 全场景实现镜像上传、用户创建、云主机部署全流程

一、python-Restful Api 简介 Restful API 是一种软件架构风格,基于 HTTP 协议设计,通过统一的接口(如 URL 路径)和标准的 HTTP 方法(GET/POST/PUT/DELETE 等)实现资源(如数据、文件等)的操作,具有无状态、可缓存、客户端 - 服务器分离等特点。方法如下 用 GET 请求获…

RxJava 在 Android 中的深入解析:使用、原理与最佳实践

前言RxJava 是一个基于观察者模式的响应式编程库&#xff0c;它通过可观察序列和函数式操作符的组合&#xff0c;简化了异步和事件驱动程序的开发。在 Android 开发中&#xff0c;RxJava 因其强大的异步处理能力和简洁的代码风格而广受欢迎。本文将深入探讨 RxJava 的使用、核心…