react笔记_08生命周期

news2024/11/20 10:20:32

目录

      • 生命周期(旧)
        • 生命周期
          • componentWillMount
          • componetdidMount
          • shouldComponentUpdate
          • componentWillUpdate
          • componentDidUpdate
          • componentWillUnmount
          • componentWillReceiveProps
        • 组件的挂载、更新、销毁
          • 案例1
          • 渲染过程
          • 更新过程1-通过setState去修改数据
          • 更新过程2-通过forceUpdate强制更新
          • 销毁过程
        • 父子组件的挂载、更新、销毁
          • 案例2
          • 渲染过程
          • 更新过程1-通过setState去修改数据(num)
          • 更新过程1-通过setState去修改数据(value)
          • 更新过程3-通过forceUpdate强制更新
          • 销毁过程
      • 生命周期(新)
        • 生命周期图

组件从创建到销毁会经历一系列的特定的阶段,React组件中会包含一系列的生命周期钩子,会在特定时刻调用。
在此将以类组件为例,讲述一下组件的挂载、更新、卸载的过程。

生命周期(旧)

生命周期

在这里插入图片描述

componentWillMount
componetdidMount
shouldComponentUpdate

在react开发中, 大部分数据需要使用state存储,更改时使用setState去修改。
默认情况下,在通过setState去修改数据时会重新渲染整个组件树,若是在某次setState更改数据时不想要重新渲染,可以在shouldComponentUpdate 生命周期钩子中做判断。
在该生命周期函数中,若是返回值为true表示重新渲染,若是返回值为false表示不重新渲染(即使数据改变了)
默认

shouldComponentUpdate(nextProps, nextState){
 return true 
}

若是在组件中没有显示声明该生命周期,默认情况下会重新渲染整个dom树。
声明
声明该函数时,当通过setState去修改数据时,react会调用此函数并传入两个参数

  • nextProps : 表示下一个props
  • nextState: 表示下一个state的值

可以对比当前props与下一次的props、当前state与下一次的state来决定是否需要重新渲染组件;
若是当前state中传入的值和通过props接收的值在修改时都需要重新渲染,那么就不需要声明该函数。

componentWillUpdate
componentDidUpdate

该组件有两个参数 preState preprops

componentWillUnmount
componentWillReceiveProps

组件即将接受props

组件的挂载、更新、销毁

案例1

在这里插入图片描述

  • 如上图 数量num存储在state中;
  • 当点击按钮 “点我加1” 时会通过 setState 去修改state中的num值;
  • 当点击 “点我强制更新” 时会通过 forceUpdate 去强制更新页面;
  • 当点击 “点我销毁组件” 时会 取消该组件的挂载;
<div id="test"></div>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- 案例:数值 按钮(每次点击按钮数字加1) -->
<script type="text/babel">
  class Mycomponent extends React.Component{
    constructor(props){
      console.log('---constructor---')
      super(props)
      this.state={num:0}
    }
    render(){
      console.log('---render---')
      return (
        <div >
          <span ref='span'>{this.state.num}</span>
          <button onClick={this.addNum}>点我加1</button>
          <button onClick={this.force}>点我强制更新</button>
          <button onClick={this.unmount}>点我销毁组件</button>
        </div>
      )
    }
    componentWillMount(){
      console.log('---componentWillMount---', this.state, this.refs) //{num:0},{}
    }
    componentDidMount(){
      console.log('---componentDidMount---', this.state, this.refs) // {num:0},{span:span(dom)}
    }
    shouldComponentUpdate(){
      console.log('---shouldComponentUpdate---')
      // return false // 及时通过setState更新状态视图也不会重新渲染
      return true // 默认返回值
    }
    componentWillUpdate(){
      console.log('---componentWillUpdate---')
    }
    componentDidUpdate(){
      console.log('---componentDidUpdate---')
    }
    addNum = ()=>{
      const {num} = this.state
      this.setState({num:num+1})
    }
    force = ()=>{
      this.forceUpdate()
      // 不会判断需不需要更新-直接更新
    }
    unmount = ()=>{
      ReactDOM.unmountComponentAtNode( document.getElementById('test')) // 销毁组件而不能销毁节点
    }
    componentWillUnmount(){
      console.log('---componentWillUnMount----')
    }
  }
  ReactDOM.render(<Mycomponent /> , document.getElementById('test'))
</script>
渲染过程

结合生命周期图以及案例1理解一下渲染过程:

  • [1]
    ReactDOM.render(<Mycomponent /> , document.getElementById('test'))
    
    发现标签名首字母大写 -> 去寻找对应的组件
  • [2] 发现组件是一个类组件 -> 通过new关键字实例化对象
    • 在实例化对象过程中,会自动调用 构造器(constructor) -> 创建实例对象并修改this指向;
  • 获取到实例化对象后
    • [3] 通过实例化对象调用componentWillMount函数 -> 在此已经初始化数据但是还没有挂载dom
    • [4] 通过实例化对象调用render函数 -> 在此获取虚拟dom
    • [5] 通过实例化对象调用componetdidMount函数 -> 在此vdom已经挂载到dom元素上

因此在案例1中,一进入页面就会在控制台打印如下
在这里插入图片描述

更新过程1-通过setState去修改数据

结合生命周期图以及案例1理解一下更新过程:

  • [1] 当点击“点我加1”按钮时,会通过setState去修改state中的数据
  • [2] 当通过setState去修改数据时,react会通过实例化对象调用shouldComponentUpdate-> 判断组件是否应该被更新
    • 返回值为true -> 组件确认被更新
      • [3] 调用 componentWillUpdate ->组件即将被更新
      • [4] 调用 render -> 获取更新后的vdom
      • [5] 调用 componentDidUpdate -组件已经被更新
    • 返回值为false -> 组件确认不更新 ->结束

因此在案例1中,点击“点我加1”按钮时就会在控制台打印如下
在这里插入图片描述
若是将shouldComponentUpdate钩子的返回值改为false, 则点击“点我加1”按钮时就会在控制台打印如下
在这里插入图片描述
–> 返回值为false更新停止;

更新过程2-通过forceUpdate强制更新

结合生命周期图以及案例1理解一下更新过程:

  • 当点击“点我强制更新”按钮时,会去重新渲染整个组件树(不会去判断是否需要更新)
  • 更新过程
    • [1]调用 componentWillUpdate ->组件即将被更新
    • [2] 调用 render -> 获取更新后的vdom
    • [3] 调用 componentDidUpdate -组件已经被更新

因此在案例1中,点击“点我强制更新”按钮时就会在控制台打印如下
在这里插入图片描述

销毁过程

结合生命周期图以及案例1理解一下销毁过程:

  • 当点击“点我销毁组件”按钮时,会去卸载dom
  • 销毁过程
    + 调用 componentWillUnmount ->组件即将被销毁

因此在案例1中,点击“点我销毁组件”按钮时就会在控制台打印如下
在这里插入图片描述

父子组件的挂载、更新、销毁

案例2

在这里插入图片描述

  • 如上图 在父组件的state中定义了两个数据-value、num
    • value在自身组件中使用
    • num传递给了子组件在子组件中使用
  • 当点击 “点我修改num” 按钮时会通过setState去修改 父组件的num值;
  • 当点击“点我修改value” 按钮时会通过setstate去修改父组件的value值;
  • 当点击 “点我强制刷新” 按钮时会重新渲染父组件的组件树;
<div id="test"></div>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel"> 
  class Fa extends React.Component{
    constructor(props){
      super(props)
      this.state ={ value:111, num:0 }
      console.log('父组件-constructor')
    }
    render(){
      console.log('父组件-render')
      return (
        <div>
          <h1>我是父组件</h1>
          {this.state.value}
          <button onClick={this.editnum}> 点我修改num</button>
          <button onClick={this.editvalue}> 点我修改value</button>
          <button onClick={this.force}> 点我强制刷新</button>
          <Son num={this.state.num}/>  
        </div>
      )
    }
    componentWillMount(){
      console.log('父组件-componentWillMount')
    }
    componentDidMount(){
      console.log('父组件-componentDidMount')
    }
    shouldComponentUpdate(){
      console.log('父组件-shouldComponentUpdate')
      return true
    }
    componentWillUpdate(){
      console.log('父组件-componentWillUpdate')
    }
    componentDidUpdate(){
      console.log('父组件-componentDidUpdate')
    }
    componentWillUnmount(){
      console.log('父组件-componentWillUnmount')
    }

    editnum = ()=>{
      const {num} = this.state
      this.setState({num:num+1})
    }
    editvalue = ()=>{
      const {value} = this.state
      this.setState({value:value+1})
    }
    force = ()=>{
      this.forceUpdate()
      // 不会判断需不需要更新-直接更新
    }

  }
  class Son extends React.Component{
    constructor(props){
      super(props)
      console.log('子组件-constructor')
    }
    render(){
      const {num} = this.props
      console.log('子组件-render')
      return(
        <div>
          <h1>我是子组件</h1>
          <span>{num}</span>
        </div>
      )
    }
    componentWillReceiveProps(props){
      console.log('接收props', props)
    }
    componentWillMount(){
      console.log('子组件-componentWillMount')
    }
    componentDidMount(){
      console.log('子组件-componentDidMount')
    }
    shouldComponentUpdate(){
      console.log('子组件-shouldComponentUpdate')
      return true
    }
    componentWillUpdate(){
      console.log('子组件-componentWillUpdate')
    }
    componentDidUpdate(){
      console.log('子组件-componentDidUpdate')
    }
    componentWillUnmount(){
      console.log('父组件-componentWillUnmount')
    }

  }
  ReactDOM.render(<Fa /> , document.getElementById('test'))
</script>
渲染过程

案例2一进入页面,在控制台打印结果如下:
在这里插入图片描述
挂载组件是一个由内向外的过程.

  • [1]
    ReactDOM.render(<Fa /> , document.getElementById('test'))
    
    (父)发现标签名首字母大写 -> 去寻找对应的组件
  • [2] (父)发现组件是一个类组件 -> 通过new关键字实例化对象。在创建实例化对象过程中,会自动调用 构造器(constructor) -> 创建实例对象并修改this指向;
  • 获取到实例化对象后
    • [3] (父)通过实例化对象调用componentWillMount函数 -> 在此已经初始化数据但是还没有挂载dom
    • [4] (父)通过实例化对象调用render函数 -> 在此获取虚拟dom
    • [5] (父-子)此时发现虚拟dom中存在组件 -> 去寻找对应的组件
    • [6] (子)发现子组件是一个类组件 -> 通过new关键字实例化对象
      • (子)在实例化对象过程中,会自动调用 构造器(constructor) -> 创建实例对象并修改this指向;
    • 获取到实例化对象后
      • [7] (子)通过实例化对象调用componentWillMount函数 -> 在此已经初始化数据但是还没有挂载dom
      • [8] (子)通过实例化对象调用render函数 -> 在此获取虚拟dom
      • [9] (子)挂载dom是一个由内向外的过程,通过实例化对象调用componetdidMount函数 -> 在此vdom已经挂载到dom元素上
    • [10] (父)通过实例化对象调用componetdidMount函数 -> 在此vdom已经挂载到dom元素上
更新过程1-通过setState去修改数据(num)

更新组件是一个由内向外的过程.

案例2当点击“点我修改num”按钮时,在控制台打印结果如下:
在这里插入图片描述

  • (父)判断是否需要更新
    • 不需要更新-> 结束(子组件也不会更新了)
    • 需要更新 -> 进行更新
      • (父)shouldComponentUpdate
      • (父)render -> 获取更新后的vdom -> 发现存在子组件
      • (子)componentWillReceiveProps -> 组件即将接收props
      • (子)判断是否需要更新
        • (子)不需要更新-> 子组件更新结束
        • (子)需要更新 -> 进行更新
          • (子)shouldComponentUpdate
          • (子)render -> 获取更新后的vdom
          • (子)componentDidUpdate
            +(父)componentDidUpdate
更新过程1-通过setState去修改数据(value)

案例2当点击“点我修改value”按钮时,在控制台打印结果如下:
在这里插入图片描述
发现value和子组件没有任何关系,当value改变时子组件依旧会重新渲染,也就是说只要是组件通过setState去修改数据,默认情况下会重新渲染整个组件树(包含子组件)。
若是不想重新渲染子组件,可以这样写

shouldComponentUpdate(nextprops){
  console.log('子组件-shouldComponentUpdate', nextprops)
  return nextprops.num != this.props.num
    }

这样就是仅仅在num值改变时才会重新渲染子组件了。

  • 若是修改num, 控制台打印结果如下:
    • 在这里插入图片描述
  • 若是修改value,控制台打印结果如下:
    • 在这里插入图片描述
更新过程3-通过forceUpdate强制更新

案例2当点击“点我强制刷新”按钮时,在控制台打印结果如下:
在这里插入图片描述

  • 当通过forceUpdate强制刷新时
    • 父组件是强制刷新
    • 子组件还是会走shouldComponentUpdate钩子去判断是否刷新.
销毁过程

销毁组件也是一个由内向外的过程.

生命周期(新)

生命周期图

在这里插入图片描述
在17版本+
不推荐使用:componentWillMount componentWillUpdate componentWillReceiveProps 不推荐使用,使用时会报一个警告
新添加两个生命周期钩子(使用较少):
getDerivedStateFromProps
该函数的参数为props state
该函数的返回值将直接作为state值进行渲染->应用在state的值在任何时候都依赖于props
getSnapshotBeforeUpdate
该函数的参数 preprops prestate 传递组件更改前的一些信息
该函数的返回值将作为 conponentDidUpdate生命周期的第三个参数

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

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

相关文章

用Python分析《阿凡达·水之道》的豆瓣短评

《阿凡达水之道》于2022年12月16日上映。第一部的口碑、评分等都非常高&#xff0c;第二部是否能延续呢&#xff0c;本文获取了该电影的豆瓣短评&#xff0c;进行了初步的分析&#xff0c;看下观众都是如何评价的。 数据获取 打开豆瓣首页&#xff0c;搜索电影名&#xff0c;进…

Spring(三): 使用注解来存储和读取Bean对象

目录一、存储Bean对象1.1 配置扫描路径1.2 使用注解存储Bean对象1.3 通过上下文读取Bean对象1.4 Bean命名规则1.5 方法注解 Bean1.5 重命名Bean二、获取Bean对象2.1 属性注入2.2 Setter注入2.3 构造方法注入2.4 Resource注解2.5 Resource注解中name参数的作用一、存储Bean对象 …

说明书丨艾美捷Annexin-V-Cy3凋亡检测试剂盒

Cy3标记的重组人膜联蛋白V显示亮红色荧光&#xff08;Ex&#xff08;max&#xff09;:543nm&#xff1b;Em&#xff08;最大值&#xff09;&#xff1a;570nm&#xff09;。 艾美捷Annexin-V-Cy3凋亡检测试剂盒化学性质&#xff1a; Applications: Flow Cytometry, Fluorescen…

C++【修理之路】初识string

这里写目录标题为什么学习string类&#xff1f;标准库中的string类string的定义转换为C风格的字符串string类的输出和输出访问字符串中的字符字符串的拼接string 字符串的增删改查总结为什么学习string类&#xff1f; C语言中&#xff0c;字符串是以’\0’结尾的一些字符的集合…

3D数学之四元数 学习笔记

四元数有三个虚部&#xff0c;一个实部 [ w (x y z) ] w xi yj zk i j k ijk -1 用于表示&#xff0c;物体在空间中的任意角度旋转 四元数的模 Sqrt(pow(w, 2) pow(x, 2) pow(y, 2) pow(z, 2)) 四元数共轭&#xff1a;p a bi 共轭为&#xff1a; p a - bi …

一文梳理 | 电力企业网络安全管理及等级保护工作重点

前言 为加强电力行业网络安全监督管理&#xff0c;规范电力行业网络安全工作&#xff0c;国家能源局近日印发《电力行业网络安全管理办法》和《电力行业网络安全等级保护管理办法》&#xff08;以下简称“两办法”&#xff09;&#xff0c;有效期均为5年。随着这两部规范性文件…

门神 马丁内斯 要什么样的成就,才不枉这些年的颠沛流离

2022-12-18日 随着劳塔罗的最后一球波网而入 阿根廷成功获得了卡塔尔世界杯的冠军 结束后 所有人都去拥抱劳塔罗 只有梅西拉起了倒在地上的马丁内斯 很多人说 在这次比赛中 阿根廷有两个神 一个是球王梅西 另一个则是 门将 马丁内斯 当场上二比零时 所有人都以为阿根廷胜券在…

(二)汇编语言——寄存器

目录 通用寄存器 汇编指令 物理地址 接下来我们来介绍寄存器&#xff0c;同时会介绍一些基本的语句&#xff08;mov,add等)&#xff0c;好了&#xff0c;就让我们进入今天的学习吧&#xff01;同时&#xff0c;我们以8086为例子来介绍&#xff0c;参考来自王爽老师的书。 说…

JAVA架构与开发(从0开始搭建一个springCloud web项目)

从0开始搭建一个springCloud web项目。 一、首先需要的开发工具&#xff1a; 1、SpringToolSuite4 &#xff0c;个人目前用的最熟练的JAVA开发工具。 2、JDK1.8&#xff0c;按照网上安装jdk的步骤安装就行。 3、maven-3.6.1 4、springBoot官网 Spring Boot 5、配置中心 Apo…

架构师必读 —— 逻辑模型(14)

从"is/is not" "before / after”的角度思考 遇到问题时&#xff0c;为了研究“为什么会发生这种问题”&#xff0c;可以将问题发生之前和发生后做一个对比&#xff0c;这样效果会更明显。通过明确差距&#xff08;差异&#xff09;&#xff0c;可以比较"在…

前端学习-创建vue项目

1.下载vscode windows系统安装第一个 linux系统安装第二个 苹果系统安装第三个 vscode 官网下载地址 下载地址&#xff1a;https://code.visualstudio.com/Download 2.下载git 选择对应的系统下载&#xff0c;跟随官网提示操作 下载地址&#xff1a;https://git-scm.com/down…

C++多线程编程基础

1.创建线程Thread 首先要引入头文件#include&#xff0c;管理线程的函数和类在该头文件中声明&#xff0c;其中包括std::thread类。 语句"std::thread th1(proc1);"创建了一个名为th1的线程&#xff0c;并且线程th1开始执行。 实例化std::thread类对象时&#xff…

你知道什么是 @Component 注解的派生性吗?

对于 Component 注解在日常的工作中相信很多小伙伴都会使用到&#xff0c;作为一种 Spring 容器托管的通用模式组件&#xff0c;任何被 Component 注解标注的组件都会被 Spring 容器扫描。 那么有的小伙伴就要问了&#xff0c;很多时候我们并没有直接写 Component 注解呀&…

计算机毕设Python+Vue寻人系统设计(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Spring Boot日志文件

哈喽呀&#xff0c;你好呀&#xff0c;欢迎呀&#xff0c;快来看一下这篇宝藏博客吧~~~ 目录 1.日志快速扫盲 2.Spring Boot项目日志简单分析 3.自定义打印日志 4.通过设置日志的级别来筛选和控制日志输出的内容 5.日志持久化 1.日志快速扫盲 什么是日志?说白了就是控制…

Java学习笔记——Idea集成git

Idea集成git-创建本地仓库-提交代码

深入浅出pom.xml文件

前言 在每一个pom文件的开头都会有这样几行代码 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocatio…

Spring Boot3.0正式发布及新特性解读

Spring Boot 3.0 正式发布 同时发布更新的还有 2.7.x 和 2.6.x 两条版本线&#xff0c;Spring Boot 是我见过的发版最守时的技术框架之一。 Spring Boot 3.0 现已正式发布&#xff0c;它包含了 12 个月以来 151 个开发者的 5700 多次代码提交。这是自 4.5 年前发布 2.0 以来&a…

Live800:在线客服系统排名是怎么样的?

在线客服系统排名是怎么样的?在线客服系统提供商提供哪些服务?在线客服系统评测要点?这些都是企业很关心的问题,这里进行简要的解答。 在线客服系统排名是怎么样的? 客观来说在线客服系统没有统一的行业标准,因此也没有统一的排名。各在线客服系统厂商各有特色,行业竞争激…

【大数据】python连接并使用redis

文章目录redis安装redis连接python安装redis库conda下载及配置vs连接redisredis使用stringset设置getrange截取append追加内容strlen(key) 字节长度listlpush,rpush赋值lpushx,rpushx只给存在的键值赋值llen 列表个数linsert 在某一个值前或者后插入新值lset 对某一个索引位置赋…