• react-节点更新与销毁


    更新与销毁

    发生更新的场景:

    1. 重新调用ReactDOM.render,触发根节点更新
    2. 在类组件中调用setState,会导致该节点更新

    节点更新

    分为两种:

    • 如果调用的是ReactDOM.render,进入根节点的对比更新(也被称为diff算法)
    • 如果调用的是setState
      1. 运行生命周期函数, static getDerivedStateFromProps
      2. 运行shouldComponentUpdate,如果该函数返回false,则终止当前流程
      3. 运行render,得到一个新节点,对新节点进行对比更新
      4. 生命周期函数getSnapshotBeforeUpdate加入执行队列
      5. 生命周期函数componentDidUpdate加入执行队列

    以上不管是哪一种,都要进行后续步骤:

    1. 更新虚拟DOM树
    2. 完成真实DOM的更新
    3. 调用执行队列中的componentDidMount、getSnapshotBeforeUpdate、componentDidUpdate

    componentDidMount来源于新子代类组件的挂载

    对比更新

    将心产生的节点,对比之前虚拟DOM树中的节点,发现差异,完成更新

    react为了提高对比效率,做出以下假设:

    • 假设节点不会出现层次的移动

      层次的移动就是比如原来A组件在第三层第一位,不会突然跑到第二层去
      对比的时候,react会直接找到旧树中该节点所在的对应位置进行对比

    对比的方式:

    1. 不同的节点类型会生成不同的解构

      名词解释
      相同的节点类型: 节点本身类型相同(不管属性,虚拟DOM树更新前后节点都为div则相同,前为div后为p则不相同),如果是react元素则要求type值必须一致
      不同的节点类型: 非相同节点类型

    2. 多个兄弟通过唯一标识(key)来确定对比的新节点

      key值的作用: 用于通过旧节点,寻找对应的新节点,如果某个旧节点由key值,则其更新时,会在相同层级中找相同的key值进行对比
      key值应该在一个范围内(兄弟节点中)唯一,并且应该保持稳定(不要使用随机数之类的)

    react依靠假设进行寻找,产生两种情况(找到与未找到)

    找到了对比目标

    如果找到了对比目标, 则进行节点类型判断

    • 节点类型一致
      根据不同的节点类型做不同的事情
      - 空节点: 不做任何事
      - DOM节点
      1. 直接重用之前的真实DOM对象
      2. 对比属性,将变动的属性记录下来,以待将来统一更新(现在不会发生变化)
      将来是啥时候? 往上看有个后续步骤,看到真实DOM更新了吗? 那就是将来
      3. 遍历该新React元素的子元素,进行递归对比更新
      递归对比更新: 说白了就是拿子元素重新走一遍更新流程
      - 文本节点
      a. 重用之前的真实DOM对象
      b. 将新的文本变化记录下来,将来完成更新
      - 组件节点: 分为函数组件与类组件
      - 函数组件: 重新调用函数,得到一个新的节点对象,进行递归对比更新
      - 类组件:
      1. 重用之前的实例,
      2. 调用生命周期方法 static getDerivedStateFromProps
      3. 调用生命周期方法shouldComponentUpdate, 若该方法返回false,则终止
      4. 运行render,得到新的节点对象,进行递归对比更新
      5. 生命周期函数getSnapshotBeforeUpdate加入执行队列
      6. 生命周期函数componentDidUpdate加入执行队列
      - 数组节点: 遍历数组, 进行递归对比更新

    • 节点类型不一致
      创建新节点 : 进入新节点挂载流程(首次渲染)
      卸载旧节点:
      1. 文本节点、DOM节点、数组节点、空节点、函数组件节点: 直接放弃该节点,如果节点有子节点,递归卸载节点
      2. 类组件节点
      - 直接放弃该节点
      - 调用该节点的componentWillUnMount函数
      - 递归卸载子节点

    没有找到对比目标

    • 创建新加入的节点
    • 卸载多余的节点
  • 相关阅读:
    Day698.Tomcat的日志框架及实战 -深入拆解 Tomcat & Jetty
    nginx反向代理location和proxy_pass的映射关系
    Java从入门到架构师__JavaSE
    GGAI重磅发布《自动泊车行业发展蓝皮书》: 竞争格局生变,谁在领跑市场?
    潘爱民:计算机程序的演进——我的程序人生三十年
    Polygon zkEVM zkASM语法
    MTK平台Metadata的加载(3)——其他Static和Request加载
    注解@TableField(value)
    构建端到端的开源现代数据平台
    Python得到字符的阿斯克码值 chr ord
  • 原文地址:https://blog.csdn.net/yuey0809/article/details/126172182