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

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.xdnf.cn/news/17813.html

相关文章:

  • linux远程部署dify和mac本地部署dify
  • 机器学习—— TF-IDF文本特征提取评估权重 + Jieba 库进行分词(以《红楼梦》为例)
  • 能刷java题的网站
  • ROS教育中自动驾驶机器人的技术融合与技术创新
  • 如何将 AGV 叉车成功集成到仓库自动化系统中?
  • Apache 服务器基础配置与虚拟主机部署
  • AI智能体如何从错误中学习:反思机制详解
  • Flutter ExpansionPanel组件(可收缩的列表)
  • 云原生作业(tomcat)
  • 异或和查询
  • echarts配置项详细解释
  • C99中的变长数组(VLA)
  • THCV215一种高速视频数据收发器,采用低电压差分信号(LVDS)技术支持高速串行数据传输,支持1080p/60Hz高分辨率传输
  • 计算机网络---默认网关(Default Gateway)
  • C++ Rust与Go
  • Vue接口平台小功能——发送报告到飞书
  • 计算机网络摘星题库800题笔记 第4章 网络层
  • nurbs曲线的matlab
  • 10. React组件间的通信
  • 数据分析基本内容(第二十节课内容总结)
  • Milvus入门:开源向量数据库,解锁大模型时代的高效检索
  • kafka初步介绍
  • 不废话,UE5极速云渲染操作方法
  • STM32_bug总结(TIM定时中断进不去和只进1次)
  • MyBatis持久层实现
  • 全面解析MySQL(5)——“索引、事务、JDBC”三大核心
  • PostgreSQL——数据查询
  • 【K8s】部署安装K8s为什么要关闭swap分区?
  • Day50--图论--98. 所有可达路径(卡码网),797. 所有可能的路径
  • 元宇宙虚拟金融服务全景解析:技术创新、场景重构与未来趋势