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

dedecms 网站地图昆明seo推广外包

dedecms 网站地图,昆明seo推广外包,河南室内设计网,今日西安最新通知vue3diff算法 什么是vue3diff算法 Vue3中的diff算法是一种用于比较虚拟DOM树之间差异的算法,其目的是为了高效地更新真实DOM,减少不必要的重渲染 主要过程 整个过程主要分为以下五步 前置预处理后置预处理仅处理新增仅处理后置处理包含新增、卸载、…

vue3diff算法

什么是vue3diff算法

Vue3中的diff算法是一种用于比较虚拟DOM树之间差异的算法,其目的是为了高效地更新真实DOM,减少不必要的重渲染

主要过程

整个过程主要分为以下五步

  1. 前置预处理
  2. 后置预处理
  3. 仅处理新增
  4. 仅处理后置
  5. 处理包含新增、卸载、移动的复杂场景

第一步:前置预处理

首先定义一个变量i,记录当前索引值
定义e1、e2记录前置索引值
从前到后遍历新旧索引列表
发现它们的节点值相同,则直接patch打补丁更新
否则跳出循环进入下一步。
vue3源码:

    let i = 0const l2 = c2.lengthlet e1 = c1.length - 1 // prev ending indexlet e2 = l2 - 1 // next ending index// 1. sync from start// (a b) c// (a b) d ewhile (i <= e1 && i <= e2) {const n1 = c1[i]const n2 = (c2[i] = optimized? cloneIfMounted(c2[i] as VNode): normalizeVNode(c2[i]))if (isSameVNodeType(n1, n2)) {patch(n1,n2,container,null,parentComponent,parentSuspense,namespace,slotScopeIds,optimized,)} else {break}i++}

以下demo为例:

i=0 新旧节点都是n1 patch打补丁更新
i=1 新旧节点都是n2 patch打补丁更新
i=2 新节点n3!== n2 跳出循环
在这里插入图片描述

第二步:后置预处理

从后到前去遍历新旧索引列表
发现它们的节点相同,则直接patch
打更新
否则跳出循环
并记录e1 e2的值

vue3源码:

        // 2. sync from end// a (b c)// d e (b c)while (i <= e1 && i <= e2) {const n1 = c1[e1]const n2 = (c2[e2] = optimized? cloneIfMounted(c2[e2] as VNode): normalizeVNode(c2[e2]))if (isSameVNodeType(n1, n2)) {patch(n1,n2,container,null,parentComponent,parentSuspense,namespace,slotScopeIds,optimized,)} else {break}e1--e2--}

以下demo为例:

e1=6、e2=6对应都是n7节点,patch打补丁更新
e1=5、e2=5对应的新旧节点不同
跳出循环,记录e1、e2的值

在这里插入图片描述

第三步:处理仅有新增节点情况

当i > e1 并且i <= e2 :代表仅有新增节点
则直接patch打补丁更新

vue3源码:

     // 3. common sequence + mount// (a b)// (a b) c// i = 2, e1 = 1, e2 = 2// (a b)// c (a b)// i = 0, e1 = -1, e2 = 0if (i > e1) {if (i <= e2) {const nextPos = e2 + 1const anchor = nextPos < l2 ? (c2[nextPos] as VNode).el : parentAnchorwhile (i <= e2) {patch(null,(c2[i] = optimized? cloneIfMounted(c2[i] as VNode): normalizeVNode(c2[i])),container,anchor,parentComponent,parentSuspense,namespace,slotScopeIds,optimized,)i++}}}

以下demo为例:
i = 2时,新旧节点不同,从后往前遍历
e1=2、e2=6对应都是n7节点,patch打补丁更新
e1=1、e2=5对应的新旧节点不同
这时i > e1 并且i <= e2,仅有新增节点,直接更新

在这里插入图片描述

第四步:处理仅有卸载节点情况

当i > e2 并且i <= e1 :代表仅有卸载节点
则直接卸载节点

vue3源码:

     // 4. common sequence + unmount// (a b) c// (a b)// i = 2, e1 = 2, e2 = 1// a (b c)// (b c)// i = 0, e1 = 0, e2 = -1else if (i > e2) {while (i <= e1) {unmount(c1[i], parentComponent, parentSuspense, true)i++}}

以下demo为例:
i = 2时,新旧节点不同,从后往前遍历
e1=2、e2=6对应都是n7节点,patch打补丁更新
e1=5、e2=1对应的新旧节点不同
这时i > e2 并且i <= e1 ,仅有卸载节点,直接卸载

在这里插入图片描述

第五步:处理其他情况(新增、卸载、移动)

定义以下变量

变量定义
s1记录旧节点列表要处理部分的起始位置
s2记录新节点列表要处理部分的起始位置
keyToNewIndexMap新节点位置映射表;用于映射新节点与位置的映射关系
newIndexToOldIndexMap新旧节点位置映射表;用于记录新旧节点位置的映射关系。初始值为0,如果都是0,则判定为新节点,需要挂载
maxNewIndexSoFar当前最远位置;用于记录新节点中当前的最远位置。目的是用于判断遍历过程中是否呈现递增趋势。如果不是则代表产生了移动
moved递减趋势,需要移动则标识为true;后续进行移动处理
j最长递增子序列位置

以下demo为列:
变动点:卸载n3 / 新增n8 / 移动n6

在这里插入图片描述
当s1=2 : n3 ;在新节点位置映射表内没有找到;则为卸载,把该节点移除
当s1=3: n4; 在新节点位置映射表中可以找到;则将s1 + 1 = 4放在新旧节点位置映射表中。同时对比新节点位置索引和最远位置,3 > 0,则将新索引位置记录到最远位置中。最后打补丁更新
在这里插入图片描述
当s1=4: n5; 在新节点位置映射表中可以找到;则将s1 + 1 = 5放在新旧节点位置映射表中。同时对比新节点位置索引和最远位置,4 > 3,则将新索引位置记录到最远位置中。最后打补丁更新
在这里插入图片描述

当s1=5: n6; 在新节点位置映射表中可以找到;则将s1 + 1 = 6放在新旧节点位置映射表中。同时对比新节点位置索引和最远位置,2 > 4,呈现递减趋势,说明位置发生了移动,则移动标识为true。最后patch打补丁更新
在这里插入图片描述
到这一步已经遍历完旧节点。这时候需要根据映射表找到最长递增子序列
目的是为了让节点做最小限度的移动操作
从下图中新旧节点映射表中可以看出:最长递增子序列索引值是4/5,将其记录下来,对应的就是1/2
从后开始往前遍历新旧节点映射表
定义变量 i 记录当前新旧节点映射表位置,
定义变量 j 记录最长递增子序列位置,初始化为1
在这里插入图片描述
当i=3:0 对应n8节点。0代表新增,挂载该节点
当i=2: 5 对应n5节点。j=1 对应最长递增子序列。因此无需移动,直接跳转
当i=1: 4 对应n4节点。j=2对应最长递增子序列中。因此无需移动,直接跳转
当i=0: 6对应n6节点。不处于最长递增子序列当中。因此需要移动,执行移动操作
这样下来,整个过程只需要挂载n8节点、卸载n3节点、移动n6节点,其他全部原地patch更新。性能得到了极大的保证

vue3源码:

     // 5. unknown sequence// [i ... e1 + 1]: a b [c d e] f g// [i ... e2 + 1]: a b [e d c h] f g// i = 2, e1 = 4, e2 = 5else {const s1 = i // prev starting indexconst s2 = i // next starting index// 5.1 build key:index map for newChildrenconst keyToNewIndexMap: Map<PropertyKey, number> = new Map()for (i = s2; i <= e2; i++) {const nextChild = (c2[i] = optimized? cloneIfMounted(c2[i] as VNode): normalizeVNode(c2[i]))if (nextChild.key != null) {if (__DEV__ && keyToNewIndexMap.has(nextChild.key)) {warn(`Duplicate keys found during update:`,JSON.stringify(nextChild.key),`Make sure keys are unique.`,)}keyToNewIndexMap.set(nextChild.key, i)}}// 5.2 loop through old children left to be patched and try to patch// matching nodes & remove nodes that are no longer presentlet jlet patched = 0const toBePatched = e2 - s2 + 1let moved = false// used to track whether any node has movedlet maxNewIndexSoFar = 0// works as Map<newIndex, oldIndex>// Note that oldIndex is offset by +1// and oldIndex = 0 is a special value indicating the new node has// no corresponding old node.// used for determining longest stable subsequenceconst newIndexToOldIndexMap = new Array(toBePatched)for (i = 0; i < toBePatched; i++) newIndexToOldIndexMap[i] = 0for (i = s1; i <= e1; i++) {const prevChild = c1[i]if (patched >= toBePatched) {// all new children have been patched so this can only be a removalunmount(prevChild, parentComponent, parentSuspense, true)continue}let newIndexif (prevChild.key != null) {newIndex = keyToNewIndexMap.get(prevChild.key)} else {// key-less node, try to locate a key-less node of the same typefor (j = s2; j <= e2; j++) {if (newIndexToOldIndexMap[j - s2] === 0 &&isSameVNodeType(prevChild, c2[j] as VNode)) {newIndex = jbreak}}}if (newIndex === undefined) {unmount(prevChild, parentComponent, parentSuspense, true)} else {newIndexToOldIndexMap[newIndex - s2] = i + 1if (newIndex >= maxNewIndexSoFar) {maxNewIndexSoFar = newIndex} else {moved = true}patch(prevChild,c2[newIndex] as VNode,container,null,parentComponent,parentSuspense,namespace,slotScopeIds,optimized,)patched++}}// 5.3 move and mount// generate longest stable subsequence only when nodes have movedconst increasingNewIndexSequence = moved? getSequence(newIndexToOldIndexMap): EMPTY_ARRj = increasingNewIndexSequence.length - 1// looping backwards so that we can use last patched node as anchorfor (i = toBePatched - 1; i >= 0; i--) {const nextIndex = s2 + iconst nextChild = c2[nextIndex] as VNodeconst anchor =nextIndex + 1 < l2 ? (c2[nextIndex + 1] as VNode).el : parentAnchorif (newIndexToOldIndexMap[i] === 0) {// mount newpatch(null,nextChild,container,anchor,parentComponent,parentSuspense,namespace,slotScopeIds,optimized,)} else if (moved) {// move if:// There is no stable subsequence (e.g. a reverse)// OR current node is not among the stable sequenceif (j < 0 || i !== increasingNewIndexSequence[j]) {move(nextChild, container, anchor, MoveType.REORDER)} else {j--}}}}

以上就是vue3 DOM DIFF算法的整个过程
vue3源码地址: https://github.com/vuejs/core
render文件:vue3\core\packages\runtime-core\src\renderer.ts

http://www.mnyf.cn/news/34758.html

相关文章:

  • 去哪个网站做兼职电商如何从零做起
  • 江苏省做网站seo关键词优化经验技巧
  • 南通网站设计公司全能搜
  • 欧洲cn2 vpsseo关键词推广怎么做
  • 放图片网站整合营销策划方案模板
  • 网站建设案例资料app运营推广是干什么
  • 福田瑞沃自卸车官网西安seo包年服务
  • wordpress the7 汉化学seo网络推广
  • 番禺品牌型网站企业网站建设报价表
  • 房产网站建设价格视频号推广
  • 小目标网站建设国外网站开发
  • 广州网站建设排名百度seo快速
  • 如何免费建设自己稳定的网站安卓优化大师下载安装
  • 如皋做网站的公司网站建设找哪家公司好
  • 找人做网站价格刷关键词排名seo
  • 红谷滩园林建设集团网站培训课程
  • 运城 网站制作seo赚钱培训课程
  • 详情页设计模板详情页设计素材优化推广关键词
  • 南昌做网站哪家公司好免费seo教程资源
  • 虎门网站建设多少钱百度seo原理
  • 做网站大概花多少钱整合营销包括哪些内容
  • 门户网站创新的方式有站长之家产品介绍
  • 贵阳公司网页网站建设网站流量排名查询工具
  • 网站模板论坛长沙做优化的公司
  • 汕头企业网站建设长沙官网seo
  • 专业的网站制作团队百度信息流投放技巧
  • 178网站建设武汉seo优化服务
  • 做网站 转行百度网站域名
  • 石家庄网站排名百度广告登录入口
  • 某网站自己做中性笔培训学校