vue diff算法 patch
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中的最后一个节点会移到最前,匹配上的两个指针向中间移动
- 如果四种匹配没有一对是成功的,那么遍历
oldChild
,S
挨个和他们匹配,匹配成功就在真实dom中将成功的节点移到最前面,如果依旧没有成功的,那么将S对应的节点
插入到dom中对应的oldS
位置,oldS
和S
指针向中间移动。
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
最新文章
- Xcode6新特性(1)-删除Main.storyboard
- Oracle 教程
- spring 的自建request请求
- Sql Server之旅——终点站 nolock引发的三级事件的一些思考
- BroadcoastReceiver之短信到来监听和获取内容
- SRM 513 2 1000CutTheNumbers(状态压缩)
- Java for LeetCode 179 Largest Number
- Temporary InMemory Tables [AX 2012]
- Azure 云平台用 SQOOP 将 SQL server 2012 数据表导入 HIVE / HBASE
- Java——函数
- Windows命令行查看文件的MD5
- max_flow(Edmond_Karp) 分类: ACM TYPE 2014-09-02 10:47 92人阅读 评论(0) 收藏
- Java appendReplacement 和 appendTail 方法
- 网站注册信息的JS全码
- 数据结构&mdash;&mdash;左高树
- Scripting Java #3:Groovy与invokedynamic
- CodeForces 631D Messenger
- Loadrunner VuGen实战---基本组成、录制流程、协议、脚本优化、参数化(三)
- Dapper批量更新
- Python 基础之----网络编程
热门文章
- Bootstrap 3之美04-自定义CSS、Theme、Package
- 重写Html.DropDownList和Html.DropDownListFor的name属性
- 报错:具有键";...";的ViewData项属于类型";...";,但它必须属于类型";IEnumerable<;SelectListItem>;";
- FT项目开发技术点(二)
- 如何在发型不乱的前提下应对单日十亿计Web请求
- ie不支持max-height的解决之法
- shader内置变量
- C#中的String与string
- vs 默认的INC和LIB
- 【BZOJ】【3053】The Closest M Points