diff算法是如何比较的,保证让你看的明明白白的!
更新dom节点,最小力度去跟新
index.html
<body>
<h1>你好啊!</h1>
<button id="btn">该变数据</button>
<div id="container"></div>
</body>
<script src="xuni/bundle.js"></script>
</html>
index.js文件
import {
init,
classModule,
propsModule,
styleModule,
eventListenersModule,
h,
} from "snabbdom";
let myVnode1 = h('ul', {}, [
h('li', {}, '姓名'),
h('li', {}, '年龄'),
h('li', {}, '爱好'),
])
// 使用init函数创建 patch函数
const patch = init([classModule, propsModule, styleModule, eventListenersModule])
const container = document.getElementById('container')
// 让虚拟节点上树
patch(container, myVnode1)
// 改变数据
let myVnode2 = h('ul', {}, [
h('li', {}, '姓名'),
h('li', {}, '年龄'),
h('li', {}, '爱好'),
h('li', {}, '性别'),
])
let btn = document.getElementById('btn')
btn.onclick = function () {
patch(myVnode1,myVnode2)
}

发现的现象
当我手动去更改页面中的数据的时候。
在点击按钮。我们发现只追加了性别。
我更改的数据并没有跟新。
说明diff是进行最小力度去跟新的
那我们把数据添加在最前面会发生什么呢?
let myVnode1 = h('ul', {}, [
h('li', {}, '姓名'),
h('li', {}, '年龄'),
h('li', {}, '爱好'),
])
// 使用init函数创建 patch函数
const patch = init([classModule, propsModule, styleModule, eventListenersModule])
const container = document.getElementById('container')
// 让虚拟节点上树
patch(container, myVnode1)
// 改变数据
let myVnode2 = h('ul', {}, [
//在最前面添加,发现跟刚才的比一样了?
//他将我们更改的数据复原了?
//这个时候又小伙伴会说,diff不是最小粒度去更新了
h('li', {}, '性别'),
h('li', {}, '姓名'),
h('li', {}, '年龄'),
h('li', {}, '爱好'),
])
let btn = document.getElementById('btn')
btn.onclick = function () {
patch(myVnode1,myVnode2)
}

diff不是最小粒度跟新?
在最前面添加,发现跟刚才的比一样了?
他将我们更改的数据复原了?
这个时候又小伙伴会说,diff不是最小粒度去更新了?
其实diff一直都是最小力度跟新,是你忘记增加key值了。
我们加上key值看看呢??
添加key值后
let myVnode1 = h('ul', {}, [
h('li', {key:'001'}, '姓名'),
h('li', {key:'002'}, '年龄'),
h('li', {key:'003'}, '爱好'),
])
// 使用init函数创建 patch函数
const patch = init([classModule, propsModule, styleModule, eventListenersModule])
const container = document.getElementById('container')
// 让虚拟节点上树
patch(container, myVnode1)
// 改变数据
let myVnode2 = h('ul', {}, [
h('li', {key:'00x'}, '性别'),
h('li', {key:'001'}, '姓名'),
h('li', {key:'002'}, '年龄'),
h('li', {key:'003'}, '爱好'),
])
let btn = document.getElementById('btn')
btn.onclick = function () {
patch(myVnode1,myVnode2)
}

添加key值顶级节点类型改变的情况
当我们添加key值后,发现数据果然是最小力度去更新的,对吧!
如果将ul更改为div,还是最小力度跟新吗?
let myVnode1 = h('ul', {}, [
h('li', {key:'001'}, '姓名'),
h('li', {key:'002'}, '年龄'),
h('li', {key:'003'}, '爱好'),
])
// 使用init函数创建 patch函数
const patch = init([classModule, propsModule, styleModule, eventListenersModule])
const container = document.getElementById('container')
// 让虚拟节点上树
patch(container, myVnode1)
// 改变数据
let myVnode2 = h('div', {}, [
h('li', {key:'001'}, '姓名'),
h('li', {key:'002'}, '年龄'),
h('li', {key:'003'}, '爱好'),
])
let btn = document.getElementById('btn')
btn.onclick = function () {
patch(myVnode1,myVnode2)
}
这个时候我们增加上key值了,按照之前的操作。
发现一个问题。数据全部恢复最初始值了。
在采取diff算法比较:新旧节点进行比较,
比较只会在同层级进行, 不会跨层级比较。
如果两个节点都是一样的,那么就深入检查他们的子节点。
果两个节点不一样那就说明 Vnode 完全被改变了(ul和div节点不一样),
就可以直接使用新节点替换老节点。【他们的子代不会进行比较了】
虽然这两个节点不一样但是他们的子节点一样怎么办?
别忘了,diff可是逐层比较的,
如果[第一层不一样那么就不会继续深入比较第二层了。
(我在想这算是一个缺点吗?相同子节点不能重复利用了??...)
这个时候你可能会说:这个diff算法也不会那么牛逼呢!
并不是最优的。
【虽然这两个节点不一样但是他们的子节点一样怎么办?】
在我们工作中:其实这指一种非常合理的机制。
我们几乎并不会出现这样的情况
<ul v-if="falg">
<li v-for="item,index" in list>{{item }}</li>
</ul>
<ol v-if="falg">
<li v-for="item,index" in list>{{item }}</li>
</ol>
这样的代码在我们工作中几乎是不会出现的呢?
什么叫做不会跨层比较?
<div>
<p>123123 </p>
</div>
与
<div>
<h2> <p>123123 </p> </h2>
</div>
div与div比较
p与h2比较
当p与h2比较的时候,他们他们节点不一样,直接使用替换。
此时并不会在使用diff了
diff算法是如何比较的,保证让你看的明明白白的!的更多相关文章
- ReactiveNative学习之Diff算法
React 源码剖析系列 - 不可思议的 react diff深入浅出React(四):虚拟DOM Diff算法解析React diff 算法总结链接引用的文章React出于性能的考虑,为了避免频繁操 ...
- Vue源码终笔-VNode更新与diff算法初探
写完这个就差不多了,准备干新项目了. 确实挺不擅长写东西,感觉都是罗列代码写点注释的感觉,这篇就简单阐述一下数据变动时DOM是如何更新的,主要讲解下其中的diff算法. 先来个正常的html模板: & ...
- 浅析vue2.0的diff算法
一.前言 如果不了解virtual dom,要理解diff的过程是比较困难的. 虚拟dom对应的是真实dom, 使用document.CreateElement 和 document.CreateTe ...
- 深入理解react中的虚拟DOM、diff算法
文章结构: React中的虚拟DOM是什么? 虚拟DOM的简单实现(diff算法) 虚拟DOM的内部工作原理 React中的虚拟DOM与Vue中的虚拟DOM比较 React中的虚拟DOM是什么? ...
- react中虚拟dom的diff算法
.state 数据 .jsx模板 .生成虚拟dom(虚拟DOM就是一个js对象,用它来描述真实DOM) ['div', {id:'abc'}, ['span', {}, 'hello world']] ...
- react性能调谐与diff算法
一个页面其实就相当于是一颗dom树,里面有很多它的子节点,然后你每次去操作一个事件,它都会生成一个虚拟dom,它会跟上一个虚拟dom进行比对,这里运用的算法叫做diff算法,当它找到需要改变的组件的时 ...
- 【Vuejs】351- 带你解析vue2.0的diff算法
前言 vue2.0加入了virtual dom,有向react靠拢的意思.vue的diff位于patch.js文件中,该算法来源于snabbdom,复杂度为O(n).了解diff过程可以让我们更高效的 ...
- 直接操作DOM一定比虚拟DOM操作耗时,diff算法,key值,虚拟 DOM的定义
直接操作DOM一定比虚拟DOM操作耗时吗? 或者一次直接DOM操作一定比一次虚拟DOM操作耗时吗? 1)虚拟DOM的本质就是一个JS对象,虚拟DOM减少了真实DOM的操作,当修改数据的时候,就是修改虚 ...
- React中diff算法的理解
React中diff算法的理解 diff算法用来计算出Virtual DOM中改变的部分,然后针对该部分进行DOM操作,而不用重新渲染整个页面,渲染整个DOM结构的过程中开销是很大的,需要浏览器对DO ...
- diff算法深入一下?
文章转自豆皮范儿-diff算法深入一下 一.前言 有同学问:能否详细说一下 diff 算法. 简单说:diff 算法是一种优化手段,将前后两个模块进行差异化比较,修补(更新)差异的过程叫做 patch ...
随机推荐
- 带你了解WDR-GaussDB(DWS) 的性能监测报告
摘要:通过本文,读者可知晓什么是WDR,如何创建性能数据快照以及生成WDR报告. 本文分享自华为云社区<WDR-GaussDB(DWS) 的性能监测报告>,作者:Zhang Jingyao ...
- 专注提升用户体验,Superset 1.3发布!
近期Superset发布了新的版本1.3.0,此版本专注于提升用户体验.并进行了大量的改进与错误修复. 用户体验 此版本的一个主要目标是改进仪表盘原生过滤器.这些过滤器的级别为仪表盘级别,而不是图表级 ...
- Java 日志框架学习笔记
日志概念 1. 日志文件 日志文件是用于记录系统操作事件的文件集合 1.1 调试日志 1.2 系统日志 系统日志是记录系统中硬件.软件和系统问题的信息,同时还可以监视系统中发生的事件.用户可以通过它来 ...
- LSP 网络劫持(Layered Service Provider Hijacking)
LSP 简介: 分层服务提供商(Layered Service Provider,LSP)是一种可以扩展Winsock作为应用程序的 Windows 的网络套接字工具的机制.Winsock LSP 可 ...
- Java异步编程详解
在现代应用程序开发中,异步编程变得越来越重要,特别是在处理I/O密集型任务时.Java提供了一套强大的异步编程工具,使得开发者能够更有效地处理并发任务.本篇博文将深入探讨Java中异步编程的方方面面, ...
- oracle开机自动重启
数据库服务器如果由于某种原因重启了,oracle数据库是不会重新启动的,那么如何配置可以完成操作系统重启数据库服务器自动重启. 注:如下样例根据我的实际oracle安装路径写的,使用时根据实际安装路径 ...
- 【转载】内存基本概念-伙伴(Buddy)算法
简介 在Linux系统中,内存的分配与回收速率直接影响系统的存取效率.当内核频繁请求和释放不同大小的一组连续页框时,会导致许多外部空闲碎片,造成空间的浪费.使用伙伴算法可以有效地缓解该问题.伙伴关 ...
- gradle简介与windows安装操作
本文为博主原创,转载请注明出处: 目录 1.Gradle 简介 2.gradel 与 maven 对比 3.安装 gradle 3.1.安装jdk 3.2.下载gradle 3.3.下载解压到指定目录 ...
- Mycat 实现分库分表及读写分离
本文为博主原创,未经允许不得转载: Mycat 官网: http://mycat.org.cn/ MyCat 权威指南 文档:http://www.mycat.org.cn/document/myca ...
- 用C# WPF简单实现仪表控件
时间如流水,只能流去不流回! 点赞再看,养成习惯,这是您给我创作的动力! 本文 Dotnet9 https://dotnet9.com 已收录,站长乐于分享dotnet相关技术,比如Winform.W ...