虚拟DOM和dom diff

简介: 虚拟DOM和dom diff

什么是虚拟DOM


虚拟DOM是一颗以JavaScript对象(node节点)作为基础的树,用对象属性来描述节点,他是对真实DOM的抽象,通过一些列操作使这棵树映射到真实环境上

虚拟dom就是能代表DOM树的对象,通常含有标签名,标签上的属性,事件监听和子元素们以及其它属性


为什么要有虚拟DOM这个东西


人们创造出虚拟 DOM 就是为了更好地将虚拟节点渲染到视图上,也就是把虚拟DOM变成真实的 DOM 节点,提高视图的渲染性能。


** 在真实DOM操作中 **


传统的开发模式,原生JS或JQ操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程。在一次操作中,我需要更新10个DOM节点,浏览器收到第一个DOM请求后并不知道还有9次更新操作,因此会马上执行流程,最终执行10次。例如,第一次计算完,紧接着下一个DOM更新请求,这个节点的坐标值就变了,前一次计算为无用功。计算DOM节点坐标值等都是白白浪费的性能。操作DOM的代价是昂贵的,频繁操作还是会出现页面卡顿,影响用户体验。


** 使用虚拟DOM **


虚拟DOM就是为了解决浏览器性能问题而被设计出来的。若一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的内容保存到本地一个JS对象中,最终将这个JS对象一次性的插入到DOM树上,再进行后续操作,避免大量无谓的计算量。所以,用JS对象模拟DOM节点的好处是,页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。


虚拟DOM的优点(为什么虚拟DOM比DOM快)


1.减少DOM的操作:


虚拟dom可以将多次操作合并为一次操作,减少DOM操作的次数。比如你添加1000个节点,确实一个接一个操作, 虚拟DOM借助DOM diff可以把多余的操作省掉,减少DOM操作的范围。比如你添加1000个节点,其实只有10个是新增的


2.跨平台渲染:


虚拟DOM不仅可以变成DOM,还可以变成小程序、 iOS应用、安卓应用,因为虚拟DOM本质上只是一个JS对象


虚拟DOM的缺点


需要额外的创建函数,如create Element或h,但是可以通过JSX来简化成XML写法


DOM diff


DOM diff 是两个虚拟 DOM 树对比的算法:diff 算法仅在两个树的同级的虚拟节点之间做比较,递归地进行比较,最终实现整个 DOM 树的更新。


diff算法的三个步骤:


  1. 用 JS 对象的方式来表示 DOM 树的结构,然后根据这个对象构建出真实的 DOM 树,插到文档中
  2. 当状态变化的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树的差异
  3. 最后把所记录的差异应用到所构建的真正的DOM树上,进行视图更新


DOM diff 在做比较时分为了三个层级、


1.Tree Diff(层级比较)


  • 先进行树结构的层级比较,对同一个父节点下的所有子节点进行比较;
  • 接着看节点是什么类型的,是组件就做 Component Diff;
  • 如果节点是标签或者元素,就做 Element Diff;


2. omponent Diff (组件比较)


  • 若组件类型相同,则继续按照层级比较其虚拟 DOM的结构;
  • 如果组件类型不同,则替换整个组件的所有内容


3. Element Diff (元素比较)


  • 如果节点是原生标签,则看标签名做比较是否相同来决定替换还是更新属性
  • 然后进入标签后代递归 Tree Diff


DOM diff的问题


同级比较存在bug,做元素比较的时候,当 DOM 处于同一层级的时候,diff 提供了三个节点操作,分别是:删除、插入和移动


key值的问题


没有使用key的时候,你想把第二个方块删除掉,你想要到的结果是剩下三角和圆圈,但是真实的结果却是剩下三角和方框


image.png


这是因为,vue做了两件事

*  把2变成3
*  把3删除掉

这有两个数组[1,2,3] 和 [1,3]。

人类会说,这不就是少了个2嘛

但是计算机不会直接删除第二个,而是会遍历数组:

首先对比1和1,发现[1没变」;然后对比2和3,发现「2变成了3」;最后对比undefined和3,发现[3被删除了」。
所以计算机的结论是:「2变成了 3」以及「3被删除了」

解决方法:

就是给每一个元素一个id,用id做key值

image.png

**为什么不能用index作为key**


如果你用index作为key,那么在删除第二项的时候,index 就会从1 23变成1 2(因为index永远都是连续的,所以不可能是1 3),

那么 Vue依然会认为你删除的是第三项。也就是会遇到上面一样的bug。

所以,永远不要用index作为key.



目录
相关文章
|
3月前
|
JavaScript 前端开发 算法
React技术栈-虚拟DOM和DOM diff算法
这篇文章介绍了React技术栈中的虚拟DOM和DOM diff算法,并通过一个实际案例展示了如何使用React组件和状态管理来实现动态更新UI。
48 2
|
4月前
|
JavaScript 前端开发 算法
react中虚拟dom和diff算法
在React中,虚拟DOM(Virtual DOM)和Diff算法是两个核心概念,它们共同工作以提高应用的性能和效率。
48 4
|
2月前
|
JavaScript 前端开发 算法
真实DOM和虚拟DOM有哪些区别?
本文介绍了真实DOM和虚拟DOM的概念、使用方式、优势、劣势、使用场景、影响因素、开发效率和性能对比。真实DOM是浏览器提供的原生接口,直接操作简单直观,但频繁操作会导致性能损耗。虚拟DOM是真实DOM的抽象表示,通过比较差异减少DOM操作,适用于大规模数据变更和复杂交互的页面。开发者应根据具体需求选择合适的DOM操作方式,以提高页面性能和开发效率。
114 1
真实DOM和虚拟DOM有哪些区别?
|
3月前
|
XML JavaScript 前端开发
学习react基础(1)_虚拟dom、diff算法、函数和class创建组件
本文介绍了React的核心概念,包括虚拟DOM、Diff算法以及如何通过函数和类创建React组件。
39 3
|
4月前
|
移动开发 JavaScript 前端开发
【Vue面试题二十二】、什么是虚拟DOM?如何实现一个虚拟DOM?说说你的思路
这篇文章深入探讨了虚拟DOM的概念、必要性以及在Vue中的实现方式,解释了虚拟DOM如何作为真实DOM的轻量级抽象,通过优化DOM操作提高性能,并实现跨平台渲染的能力。
【Vue面试题二十二】、什么是虚拟DOM?如何实现一个虚拟DOM?说说你的思路
|
3月前
|
机器学习/深度学习 JavaScript 算法
面试中的网红虚拟DOM,你知多少呢?深入解读diff算法
该文章深入探讨了虚拟DOM的概念及其diff算法,解释了虚拟DOM如何最小化实际DOM的更新,以此提升web应用的性能,并详细分析了diff算法的实现机制。
|
4月前
|
JavaScript 算法 前端开发
"揭秘虚拟DOM的神奇魔法:从零开始打造高效渲染引擎,颠覆你的DOM操作认知!"
【8月更文挑战第20天】虚拟DOM是一种优化技术,通过在内存中构建DOM树的轻量级副本,减少浏览器重排和重绘,提升性能。本文简要介绍了DOM及其重要性,并深入解释了虚拟DOM的概念。虚拟DOM通过模拟真实DOM结构,在内存中进行数据更新,仅将变动部分同步到实际DOM。文中还提供了一个简易虚拟DOM的实现方案,包括虚拟节点创建、渲染函数及一个基本的diff算法,用于比对新旧虚拟DOM并高效更新实际DOM。通过示例展示了如何构建和渲染一个简单的虚拟DOM。这有助于理解虚拟DOM的基本工作原理和技术细节。
65 4
|
4月前
|
JavaScript 前端开发 API
区分 DOM 与虚拟 DOM
【8月更文挑战第24天】
128 0
|
6月前
|
JavaScript 前端开发 算法
虚拟DOM是React的关键技术,它是个轻量的JS对象树,模拟实际DOM结构。
【6月更文挑战第27天】虚拟DOM是React的关键技术,它是个轻量的JS对象树,模拟实际DOM结构。当状态改变,React不直接修改DOM,而是先构建新的虚拟DOM树。通过 diff 算法比较新旧树,找到最小变更,仅更新必要部分,提高性能,避免频繁DOM操作。虚拟DOM还支持跨平台应用,如React Native。它优化了更新流程,简化开发,并提升了用户体验。
47 1
|
7月前
|
JavaScript 前端开发 算法
为什么需要key,dom diff
React的"key"属性和DOM diff是性能优化的关键。"key"帮助React识别列表元素身份,减少重渲染,而DOM diff通过对比新旧虚拟DOM找到最小更新,避免全树渲染。这两者结合提升性能、保证正确性并优化列表操作。正确设置"key"属性能避免错误和性能下降,实现更高效的组件更新。