diff算法是如何比较的,保证让你看的明明白白的!

简介: 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)
}


1425695-20211213212712423-1402171806.gif


发现的现象


当我手动去更改页面中的数据的时候。


在点击按钮。我们发现只追加了性别。


我更改的数据并没有跟新。


说明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)
}


1425695-20211213212749266-1274072919.gif


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)
}

1425695-20211213212759808-919555620.gif


添加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了

相关文章
|
JavaScript 前端开发 算法
React技术栈-虚拟DOM和DOM diff算法
这篇文章介绍了React技术栈中的虚拟DOM和DOM diff算法,并通过一个实际案例展示了如何使用React组件和状态管理来实现动态更新UI。
151 2
|
JavaScript 前端开发 算法
react中虚拟dom和diff算法
在React中,虚拟DOM(Virtual DOM)和Diff算法是两个核心概念,它们共同工作以提高应用的性能和效率。
135 4
|
JavaScript 算法 前端开发
vue 中diff算法
【10月更文挑战第10天】
321 137
|
算法 JavaScript
Vue 中的 Diff 算法
【10月更文挑战第18天】需要注意的是,Diff 算法虽然能够提高性能,但在某些复杂的场景下,可能仍然会存在一些性能瓶颈。因此,在实际开发中,我们需要根据具体情况合理地使用 Diff 算法,并结合其他优化手段来提高应用的性能。
183 56
|
算法 JavaScript UED
Diff 算法的实现原理
【10月更文挑战第18天】Diff 算法是 Vue.js 中实现高效 DOM 更新的核心机制,通过合理的比较和优化策略,能够在保证界面正确性的同时,最大程度地减少 DOM 操作,提高应用的性能和用户体验。
368 2
|
JavaScript 算法 前端开发
【VUE】Vue的diff算法和React的diff算法
【VUE】Vue的diff算法和React的diff算法
|
XML JavaScript 前端开发
学习react基础(1)_虚拟dom、diff算法、函数和class创建组件
本文介绍了React的核心概念,包括虚拟DOM、Diff算法以及如何通过函数和类创建React组件。
165 3
|
机器学习/深度学习 JavaScript 算法
面试中的网红虚拟DOM,你知多少呢?深入解读diff算法
该文章深入探讨了虚拟DOM的概念及其diff算法,解释了虚拟DOM如何最小化实际DOM的更新,以此提升web应用的性能,并详细分析了diff算法的实现机制。
|
前端开发 算法 JavaScript
React原理之Diff算法
【8月更文挑战第24天】
|
JavaScript 算法 前端开发
"揭秘Vue.js的高效渲染秘诀:深度解析Diff算法如何让前端开发快人一步"
【8月更文挑战第20天】Vue.js是一款备受欢迎的前端框架,以其声明式的响应式数据绑定和组件化开发著称。在Vue中,Diff算法是核心之一,它高效计算虚拟DOM更新时所需的最小实际DOM变更,确保界面快速准确更新。算法通过比较新旧虚拟DOM树的同层级节点,递归检查子节点,并利用`key`属性优化列表更新。虽然存在局限性,如难以处理跨层级节点移动,但Diff算法仍是Vue高效更新机制的关键,帮助开发者构建高性能Web应用。
264 1