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 ...
随机推荐
- 全文手敲代码,教你用Java实现扫雷小游戏
摘要:本程序共封装了五个类,分别是主类GameWin类,绘制底层地图和绘制顶层地图的类MapBottom类和MapTop类,绘制底层数字的类BottomNum类,以及初始化地雷的BottomRay类和 ...
- Android和iOS应用程序加固方法详解:混淆、加壳、数据加密、动态加载和数字签名实现
目录 Android和iOS应用程序加固方法详解:混淆.加壳.数据加密.动态加载和数字签名实现 APP 加固方式 iOS APP加固代码实现 打开要处理的IPA文件 设置签名使用的证书和描述文件 ...
- Solon Logging 日志插件的记录器、添加器级别控制
有需要的人可以记下 solon.logging.appender: console: level: TRACE #设置级别,默认为 TRACE enable: true #是否启用,默认为 true ...
- HanLP — HMM隐马尔可夫模型 -- 训练&预测
BMES => B-begin:词语开始.M-middle:词语中间.E-end:词语结束.S-single:单独成词 训练的过程,就是求三个矩阵的过程 初始概率矩阵 转移概率矩阵 发射矩阵 每 ...
- ubuntu下完全卸载重装docker教程
操作需在管理员权限下运行 卸载docker 1.删除docker的所有包 apt-get autoremove docker docker-ce docker-engine docker.io con ...
- 基于C++11特性的线程池
写在前面:本文学习自基于C++11实现线程池,代码部分均属于该博主,自己只是想记录以下自己的认知,并以这种方式加深一下自己对于多线程的理解 1 前置知识 RAII管理机制 简单来说RAII机制是一种对 ...
- AI绘画,Midjourney极简入门
前几天看报道说: 一位小哥用AI绘画工具Midjourney生成的作品,在美国科罗拉多州博览会的艺术比赛中获得了第一名. 作者表示,他多次调整了输入的提示词,生成了100多幅画作,经过数周的修改和挑选 ...
- 微信公众号短链实时阅读量、点赞数爬虫(不会Hook可用)
众所周知,微信分享的公众号分享出的一般都是短链,在这个锻炼下使用浏览器打开并不能获取微信公众的阅读量点赞数等这些信息,如图1所示. 但是实际拥有详细信息的则是这个链接下面,提取链接所需要提交的信息包括 ...
- SpringCloud Alibaba技术栈(一)微服务介绍
B 站黑马视频教程:Here 源码-笔记:Code for Github 第一章 微服务总览 1. 软件系统架构的历史 软件系统架构大致经历了:单体应用架构->垂直应用架构->分布式架构- ...
- DDD领域驱动设计 (C# 整理自“老张的哲学”)
大话DDD领域驱动设计 概念 Domain Driven Design 领域驱动设计 第一个D(Domain): 领域:指围绕业务为核心而划分的实体模块. 第二个D(Driven): 驱动:这里的驱动 ...