当前位置: 首页 > news >正文

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.dtcms.com/a/327510.html

相关文章:

  • 使用镜像网站 打开克隆 GitHub 网站仓库内容 git clone https://github.com/
  • 跟李沐动手学深度学习---学习笔记之基础篇
  • ForceVLA——将具备力感知的MoE整合进π0的动作专家中:从而融合视觉、语言、力反馈三者实现精密插拔
  • 【USRP】基于LabVIEW的BPSK、QPSK,文本,图片
  • n8n、Workflow实战
  • Redis序列化配置类
  • 【从零开始java学习|第四篇】IntelliJ IDEA 入门指南
  • 采暖管道安装、分类、计量-文字查找快速定位、批量测量一键计算
  • OBOO鸥柏丨智能会议平板教学查询一体机交互式触摸终端招标投标核心标底参数要求
  • 115-基于Flask的医疗保健数据预测分析系统
  • 2025年渗透测试面试题总结-15(题目+回答)
  • 【前端Vue】如何优雅地展示带行号的日志文件或文本内容(log-viewer组件的使用)
  • Java数据结构之ArrayList
  • 《算法导论》第 20 章 - van Emde Boas 树
  • 《前端性能监控深解:从指标捕获到数据洞察的完整脉络》
  • Windows已经安装了一个MySQL8,通过修改配置文件的端口号跑2个或多个Mysql服务方法,并注册为系统服务
  • linux远程部署dify和mac本地部署dify
  • 【3】Transformers快速入门:大语言模型LLM是啥?
  • 电商双 11 美妆数据分析总结
  • 自然语言处理( NLP)基础
  • Elasticsearch Node.js 客户端连接指南(Connecting)
  • 2025年最新原创多目标算法:多目标酶作用优化算法(MOEAO)求解MaF1-MaF15及工程应用---盘式制动器设计,提供完整MATLAB代码
  • 机器学习算法篇(十):TF-IDF算法详解与应用实战
  • 成都影像产业园实训考察:重庆五一职院关注技能就业
  • 人大BABEC地平线高效率具身导航!Aux-Think:探索视觉语言导航中数据高效的推理策略
  • PaddlePaddle 模型训练技巧
  • 深入C#异步编程基石:BeginInvoke与EndInvoke全解析
  • 代码随想录算法训练营四十二天|单调栈part02
  • 【Activiti】要点初探
  • 迈向具身智体人工智能:LLM 和 VLM 驱动的机器人自主性和交互性