简单Diff算法

本文详细介绍了虚拟DOM中的Diff算法,包括如何通过key属性复用节点、移动节点的过程以及新增和移除节点的处理。算法核心是对比新旧子节点,通过移动最少数量的DOM元素来实现高效更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简单Diff算法

渲染器的核心

Diff算法

解决的问题

比较新旧虚拟节点的子节点,实现最小化更新。

虚拟节点key属性的作用

就像虚拟节点的“身份证号”,在更新时,渲染器会通过key属性找到可复用的节点,然后尽可能地通过DOM移动操作来完成更新,避免过多地对 DOM 元素进行销毁和重建。key和type的属性值均都相同,则两个节点就是相同的,即可实现进行DOM的复用。

简单Diff算法地核心逻辑(如何寻找需要移动的节点)

拿新一组子节点中的节点去旧的一组子节点中去寻找可复用的节点。如果找到了,则记录该节点的位置索引。我们把这个索引称为最大索引。在整个更新过程中,如果一个节点的索引小于最大索引,则说明该节点需要移动。

节点的移动

使用的是insert方法,找到锚点元素进行插入操作,其中insert方法对于浏览器来说依赖于原生的insertBefore函数。

在这里插入图片描述

源码展示
function patchChildren(n1, n2, container) {
   
   
  if (typeof n2.children === 'string') {
   
   
    // 省略部分代码
  } else if (Array.isArray(n2.children)) {
   
   
    const oldChildren = n1.children;
    const newChildren = n2.children
    // 用来存储寻找过程中遇到的最大索引值
    let lastIndex = 0;
    for (let i = 0; i < newChildren.length; i++) {
   
   
      const newVNode = newChildren[i];
      for (let j = 0; j < oldChildren.length; j++) {
   
   
        const oldVNode = oldChildren[j];
        if (newVNode.key === oldVNode.key) {
   
   
          // 进行打补丁
          patch(oldVNode, newVNode, container);
          if (j < lastIndex) {
   
   
            // 如果当前找到的节点在旧节点中的索引值小于最大索引值lastIndex,
            // 说明该节点对应的真实的DOM节点需要进行移
            // 先获取 newVNode 的前一个vnode,即 preVNode
            const preVNode = newChildren[i - 1]
            // 如果 prevVNode 不存在,则说明当前的 newVNode 是第一个节点,它不需要移动
            if (prevVNode) {
   
   
              
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值