1、diff比较算法

图示:

diff比较只会在同层级进行, 不会跨层级比较。

所以diff是:广度优先算法。

时间复杂度:O(n)

代码示例:

<!-- 之前 -->
<div> <!-- 层级1 -->
<p> <!-- 层级2 -->
<b> aoy </b> <!-- 层级3 -->
<span>diff</Span>
</P>
</div> <!-- 之后 -->
<div> <!-- 层级1 -->
<p> <!-- 层级2 -->
<b> aoy </b> <!-- 层级3 -->
</p>
<span>diff</Span>
</div>

我们可能期望将<span>直接移动到<p>的后边,这是最优的操作。

但是实际的diff操作是:

(1)移除<p>里的<span>

(2)创建一个新的<span>插到<p>的后边。

因为新加的<span>在层级2,旧的在层级3,属于不同层级的比较。

一般的diff算法中都采用的是深度优先遍历。对新旧两棵树进行一次深度优先的遍历,这样每个节点都会有一个唯一的标记。在遍历的时候,每遍历到一个节点就把该节点和新的树的同一个位置的节点进行对比,如果有差异的话就记录到一个对象里面。

例如,上面的div和新的div有差异,当前的标记是0,那么:patches[0] = [{difference}, {difference}, …]。同理p是patches[1],ul是patches[3],以此类推。这样当遍历完整棵树的时候,就可以获得一个完整的差异对象。

vue源码中会有一个sameVnode方法

function sameVnode (a, b) {
return (
a.key === b.key && (
(
a.tag === b.tag &&
a.isComment === b.isComment &&
isDef(a.data) === isDef(b.data) &&
sameInputType(a, b)
) || (
isTrue(a.isAsyncPlaceholder) &&
a.asyncFactory === b.asyncFactory &&
isUndef(b.asyncFactory.error)
)
)
)
}

表示2个Vnode是否是同一个节点:

(1)当是一样的节点,直接复用(若设置key的话)

(2)当不是一样的节点的话,新节点直接替换老节点。

2、比较原则

图示:

图师说明:

粉红色的部分为oldNode,黄色的表示newNode。

s和e指针指向它们的头child和尾child Node的指针

现在分别对oldS、oldE、S、E两两做sameVnode比较,有四种比较方式。

即:

oldS == S?

oldS == E?

oldE == S?

oldE == E?

diff算法:

  • 如果是oldS和E匹配上了,那么真实dom中的第一个节点会移到最后
  • 如果是oldE和S匹配上了,那么真实dom中的最后一个节点会移到最前,匹配上的两个指针向中间移动
  • 如果四种匹配没有一对是成功的,那么遍历oldChildS挨个和他们匹配,匹配成功就在真实dom中将成功的节点移到最前面,如果依旧没有成功的,那么将S对应的节点插入到dom中对应的oldS位置,oldSS指针向中间移动。

3、key

不设key,newCh和oldCh只会进行头尾两端的相互比较。

设key后,除了头尾两端的比较外,还会从用key生成的对象oldKeyToIdx中查找匹配的节点,所以为节点设置key可以更高效的利用dom。

(1)下图是没有设置key的diff算法

(2)下图是有设置key的diff算法

参考文章:

https://www.cnblogs.com/wind-lanyan/p/9061684.html

https://segmentfault.com/a/1190000008782928?utm_source=tag-newest

vue diff算法 patch的更多相关文章

  1. vue diff 算法学习

    function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) { let oldStartIdx ...

  2. Vue diff 算法

    一.虚拟 DOM (virtual dom) diff 算法首先要明确一个概念就是 diff 的对象是虚拟DOM(virtual dom),更新真实 DOM 是 diff 算法的结果. 注:virtu ...

  3. vue是如何通过diff算法做渲染更新

    渲染页面 图中框起来的部分,vue会根据响应式变化的通知生成一颗新的 Virtual Dom Tree,然后将新的Virtual Dom Tree 和之前的 Virtual Dom Tree 做 di ...

  4. Vue源码终笔-VNode更新与diff算法初探

    写完这个就差不多了,准备干新项目了. 确实挺不擅长写东西,感觉都是罗列代码写点注释的感觉,这篇就简单阐述一下数据变动时DOM是如何更新的,主要讲解下其中的diff算法. 先来个正常的html模板: & ...

  5. 详解vue的diff算法

    前言 我的目标是写一个非常详细的关于diff的干货,所以本文有点长.也会用到大量的图片以及代码举例,目的让看这篇文章的朋友一定弄明白diff的边边角角. 先来了解几个点... 1. 当数据发生变化时, ...

  6. Vue 中 diff 算法后更新 DOM 的方法

    vue 2.0加入了 virtual dom,在 node_modules\vue\src\core\vdom\patch.js 中会对虚拟 DOM 进行 diff 算法等,然后更新 DOM. 网上的 ...

  7. vue的diff算法

    前言 我的目标是写一个非常详细的关于diff的干货,所以本文有点长.也会用到大量的图片以及代码举例,目的让看这篇文章的朋友一定弄明白diff的边边角角. 先来了解几个点... 1. 当数据发生变化时, ...

  8. 理解Vue 2.5的Diff算法

    DOM"天生就慢",所以前端各大框架都提供了对DOM操作进行优化的办法,Angular中的是脏值检查,React首先提出了Virtual Dom,Vue2.0也加入了Virtual ...

  9. vue之虚拟DOM、diff算法

    一.真实DOM和其解析流程? 浏览器渲染引擎工作流程都差不多,大致分为5步,创建DOM树——创建StyleRules——创建Render树——布局Layout——绘制Painting 第一步,用HTM ...

随机推荐

  1. GoodSync 同步 对比 备份

    单向/双向皆可,针对任何一侧的文件进行处理,两侧文件都进行更新 文件同步 的操作过程是:确保两处或多处包含完全一致.及时更新 的各种文件.当对某一处进行文件添加.更改或删除,则同步操作将对对应的 另一 ...

  2. DeJaVu update history

    17.05.08 <-> Added Audi RB8 random code direct change -> Now can adapt VIN based keys or ke ...

  3. Effective JavaScript Item 35 使用闭包来保存私有数据

    本系列作为EffectiveJavaScript的读书笔记. JavaScript的对象系统从其语法上而言并不鼓舞使用信息隐藏(Information Hiding).由于当使用诸如this.name ...

  4. go test

    testing 是go中自动测试的包, 直接import就可以使用, 使用时需要注意以下规范 执行测试函数的文件必须以 _test.go 结尾, 注意下划线 单元测试函数名必须以 Test 开头, 并 ...

  5. 《学习opencv》笔记——矩阵和图像操作——cvAbs,cvAbsDiff and cvAbsDiffS

    矩阵和图像的操作 (1)cvAbs,cvAbsdiff,cvAbsDiffS 它们的结构为: void cvAbs( //取src中元素的绝对值,写到dst中 const CvArr* src, co ...

  6. MVC扩展ActionInvoker,自定义ActionInvoker,根据请求数据返回不同视图

    ActionInvoker的作用是:根据请求数据(HttpPost,HttpGet等)和action名称,来激发响应的action,再由action渲染视图.本文通过自定义ActionInvoker, ...

  7. C\C++各路高手以及操作系统专家请进来杀死这个进程

    通常情况下编写一个程序,能够点击关闭button正常结束程序,也能够使用任务管理器结束任务,还能够使用taskkill等命令杀死进程,实在都不行也能够直接重新启动计算机. 可是,这些方法真的都管用吗? ...

  8. JTable常见用法细则

    JTable是Swing编程中很常用的控件,这里总结了一些常用方法以备查阅.欢迎补充,转载请注明作者与出处. 一.创建表格控件的各种方式:1)  调用无参构造函数. JTable table = ne ...

  9. Apache2.2.16+PHP5.3.3+MySQL5.1.49的配置方法

    第一步:下载安装的文件 1. MySQL:下载地址mysql-5.1.49-win32.msi: 2. Apache: 下载地址httpd-2.2.16-win32-x86-openssl-0.9.8 ...

  10. QT编程之——使用全局变量

    在Qt中使用全局变量的实例 1.首先须要在一个头文件里对全局了变量使用exern方法进行定义. //g.h extern char *testStr; 2.仅仅能在cpp文件里对事实上例化,而且实例化 ...