React DOM-DIFF

React中的DOM-DIFF / Fiber算法

jsx或者说React的渲染机制:

  1. 把jsx语法编译为虚拟DOM「virtualDOM」
    • 基于babel-preset-react-app把jsx视图编译为 React.createElement 格式
      React.createElement(标签名/组件名,props,…children)
    • createElement 执行就会创建出对应的 virtualDOM
  2. 基于ReactDOM 中的render 方法,把virtualDOM编译为真实DOM,最后把真实的DOM交给浏览器渲染
  3. 当组件更新的时候:
    • 会根据最新的数据,重新把”整个jsx“编译为新的 virtualDOM 「不论有的地方的数据是否发生改变,virtualDOM都是从头编译到尾的」
    • 但是不会把整个virtualDOM全部编译为真实的DOM,它需要经过一个 DOM-DIFF 的对比,把virtualDOM中差异的部分获取到,接下来只把差异的部分渲染为真实的DOM,交给浏览器渲染

React DOM-DIFF 算法在react不同版本中的实现:

  • 在ReactV16及以前:新老虚拟DOM对比
  • 在ReactV17及以后:老的DOM会构建出Fiber链表,拿最新创建的虚拟DOM和Fiber链表做对比,计算出差异的部分。

DOM-DIFF 主要就是在组件更新的时候,可以实现差异化的更新而不是整体全部更新,以此来优化组件渲染的速度,提高性能。


优化原则:

  • 深度优先原则
  • 同级对比
  • 不同类型的元素,会产出不同的结构:销毁老结构,创建新结构
  • 可以通过key标识移动的元素:如果不设置key,则默认元素的“索引”就是key

在这里插入图片描述
处理规则:

在这里插入图片描述

详细的处理步骤:

在这里插入图片描述

举例演示 && 原理说明:

import React, { useState, useEffect } from "react";
import styled from "styled-components";

const TestBox = styled.div`
    display: flex;
    div{
        margin-right: 10px;
        width: 100px;
        height: 100px;
        text-align: center;
        line-height: 100px;
        background: lightpink;
        font-size: 18px;
    }
`;

let n = 0;
const Test = function Test() {
    n++;
    let [state, setState] = useState(['A', 'B', 'C', 'D', 'E', 'F']);
    useEffect(() => {
        setTimeout(() => {
            setState(['A', 'C', 'E', 'B', 'G', 'F']);
        }, 2000);
    }, []);

    return <TestBox>
        {state.map(item => {
            return <div key={item}>
                {n > 1 ? `${item}-NEW` : item}
            </div>;
        })}
    </TestBox>;
};
export default Test;

在这里插入图片描述
在这里插入图片描述


在这里插入图片描述
在这里插入图片描述

关于索引作为key的优化

import React, { useState, useEffect } from "react";
import styled from "styled-components";

const TestBox = styled.div`
    display: flex;
    div{
        margin-right: 10px;
        width: 100px;
        height: 100px;
        text-align: center;
        line-height: 100px;
        background: lightpink;
        font-size: 18px;
    }
`;

const Test = function Test() {
    let [state, setState] = useState(['A', 'B', 'C', 'D', 'E', 'F']);
    useEffect(() => {
        setTimeout(() => {
            setState(['A', 'E', 'B', 'G', 'F']);
        }, 2000);
    }, []);

    return <TestBox>
        {state.map((item, index) => {
            return <div key={index}>
                {item}
            </div>;
        })}
    </TestBox>;
};
export default Test;

在这里插入图片描述
在这里插入图片描述
循环创建元素的时候需要设置唯一的key,我们尽可能的不要用索引作为key值,而是用一个不会因为“位置或索引”改变而改变的值做key「例如:每一项唯一的ID值等」

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值