如何优化 DOM 操作以获得更好的性能?
主题
Web APIJavaScript性能
在GitHub上编辑
TL;DR
要优化 DOM 操作以获得更好的性能,请尽量减少直接访问和更新 DOM。使用诸如批处理 DOM 更改、使用 documentFragment
处理多个元素以及利用 React 等虚拟 DOM 库等技术。此外,还可以考虑使用 requestAnimationFrame
进行动画处理,并通过分别读取和写入 DOM 属性来避免布局抖动。
如何优化 DOM 操作以获得更好的性能?
尽量减少直接 DOM 访问
访问 DOM 相对较慢,因此请尽量减少从 DOM 读取或写入 DOM 的次数。相反,将对元素的引用存储在变量中,并使用这些变量。
// Creating an element for the example belowconst newElement = document.createElement('div');newElement.id = 'myElement';document.body.appendChild(newElement);const element = document.getElementById('myElement'); // Access once// Then use the reference to edit styleelement.style.color = 'red';element.style.backgroundColor = 'blue';console.log(document.body); // Notice the edits
批处理 DOM 更改
不要一次对 DOM 进行多次更改,而是将它们批处理在一起。这减少了重排和重绘的次数。
// Creating an element for the example belowconst newElement = document.createElement('div');newElement.id = 'myElement';document.body.appendChild(newElement);const element = document.getElementById('myElement');element.style.cssText = 'color: red; background-color: blue;';console.log(document.body); // Notice the edits
使用 documentFragment
将多个元素添加到 DOM 时,使用 documentFragment
以最大限度地减少重排和重绘。
const fragment = document.createDocumentFragment();for (let i = 0; i < 100; i++) {const newElement = document.createElement('div');newElement.textContent = `Item ${i}`;fragment.appendChild(newElement);}document.body.appendChild(fragment);console.log(document.body); // Notice that the divs have been added
利用虚拟 DOM 库
React 等库使用虚拟 DOM 来批处理更新并最大限度地减少直接 DOM 操作,这可以显著提高性能。
import React from 'react';import ReactDOM from 'react-dom';const App = () => (<div><h1>Hello, world!</h1></div>);ReactDOM.render(<App />, document.getElementById('root'));
使用 requestAnimationFrame
进行动画处理
为了获得更流畅的动画效果,请使用 requestAnimationFrame
确保更新与浏览器的重绘周期同步。
function animate() {// Update animation staterequestAnimationFrame(animate);}requestAnimationFrame(animate);
避免布局抖动
当您以迫使浏览器多次重新计算样式和布局的方式反复读取和写入 DOM 时,就会发生布局抖动。为避免这种情况,请将读取和写入操作分开。
// Creating an element for the example belowconst newElement = document.createElement('div');newElement.id = 'myElement';document.body.appendChild(newElement);const element = document.getElementById('myElement');const height = element.clientHeight; // Readelement.style.height = `${height + 10}px`; // Write