为什么操作DOM消耗性能
为什么 DOM 操作浪费性能
DOM 并不属于 JS 语言的一部分,他是 JS 的运行平台浏览器提供的。nodejs 中就没有 DOM。浏览器中的 DOM 节点对应的是 HTML 页面中的元素,它本身和 JS 对象没有什么关系,但是 webkit 渲染引擎和 JS 引擎通过 JS Binding 在 V8 内部会将原生的 DOM 对象映射为 JS 对象。我们称之为包装对象。因此我们平时写代码时,操作 DOM 对象操作的就是这个包装对象。和操作 JS 对象是一样的。
浏览器设置的是 JS 线程和渲染线程是互斥的,当 JS 引擎运行时,渲染线程会被挂起,页面的更新会被保存到一个队列中,等到 JS 线程空闲时再去执行。原因是 JS 是可以操作 DOM 的,如果在修改这些元素属性的同时渲染界面,那么在渲染前后获取到的元素数据可能就不一致了。
因此,在我们操作 DOM 的时候,需要先将 JS 的数据结构转换为 DOM 的数据结构,再挂起 JS 线程并启动渲染线程,执行过后还需要反转数据结构至 JS 对象,重启 JS 线程继续执行。这种两个线程之间的上下文切换会比较耗费性能。
另外 DOM 操作还会导致页面的重绘和回流,会更加耗费性能。
总结
- 会导致页面的重绘和回流
- 涉及到渲染线程和 JS 线程的来回切换
虚拟 DOM
传统的前端编程方式是命令式编程,即直接操纵 DOM,告诉浏览器该怎么干。这样的问题就是,大量的代码被用于操作 DOM 元素,且代码可读性差,可维护性低。
虚拟 DOM 其实就是一个 JS 对象,一个用来描述真实 DOM 的 JS 对象
而 React、Vue 这些数据驱动的前端框架的出现让我们只要关心数据的变动,DOM 的操作由框架完成。将因数据变动而新生成的虚拟 DOM 树与已经显示出来的虚拟 DOM 树进行比较,找出两者的不同处,再对这些不同进行重新渲染即可。有的放矢,从而提升性能。
虚拟 DOM 比真实 DOM 快,这个说法是错误的
因为在内存中构建虚拟 DOM 以及新旧的虚拟 DOM 树对比也是需要消耗性能的。
这个和页面的大小及数据的变动量有关系。但是相比于操作 DOM,操作 JS 对象肯定是更快更简单。
为什么要用虚拟 DOM
因为真实的 DOM 操作代价昂贵,操作起来还会引起页面卡顿从而影响用户体验。而虚拟 DOM 就是为了解决浏览器的这个性能问题被创造出来的。