diff算法是如何比较的,保证让你看的明明白白的!
2021/12/13 22:18:02
本文主要是介绍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算法是如何比较的,保证让你看的明明白白的!的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南