如何将强制回流的 Javascript 操作分组?
How can I group Javascript actions that force reflow?
我有一个项目负责管理元素的渲染,但我 运行 遇到性能问题,替换元素然后专注于之前关注的内容。
下面是复制性能问题的最小示例:
const renderPage = () => {
// get the old section element
const oldSection = document.querySelector('section')
// create a new section element (we'll replaceWith later)
const newSection = document.createElement('section')
// create the render button
const newButton = document.createElement('button')
newButton.innerHTML = 'Render Page'
newButton.onclick = renderPage
newSection.appendChild(newButton)
// create a bunch of elements
const dummyDivs = [...new Array(100000)].forEach(() => {
const dummy = document.createElement('div')
dummy.innerHTML = 'dummy'
newSection.appendChild(dummy)
})
// replace the old page with the new one (causes forced reflow)
oldSection.replaceWith(newSection)
// reattach focus on the button (causes forced reflow)
newButton.focus()
}
window.renderPage = renderPage
<section>
<button onclick="renderPage()">Render</button>
</section>
当 运行 在本地时,我在 Chrome/Edge 的性能报告中看到以下内容
replaceWith
和focus
都在触发强制回流。有没有办法对这些操作进行批处理或分组,以便只发生一次回流?我意识到根本没有办法真正解决这种情况,但如果我可以对它们进行批处理,我认为这可能会提高我的表现。
确实,焦点总是导致回流:What forces layout / reflow
所以您可以做的是通过独立插入新按钮来减少回流时间,启动焦点,然后您可以附加其他子按钮:
工作示例:Example
const renderPage = () => {
// get the old section element
const oldSection = document.querySelector('section')
// create a new section element (we'll replaceWith later)
const newSection = document.createElement('section')
// create the render button
const newButton = document.createElement('button')
newButton.innerHTML = 'Render Page'
newButton.onclick = renderPage
newSection.appendChild(newButton)
// create a bunch of elements
const dummies = []; // store in seperate array
const dummyDivs = [...new Array(100000)].forEach(() => {
const dummy = document.createElement('div')
dummy.innerHTML = 'dummy';
dummies.push(dummy)
})
// insert new section only with new button
oldSection.replaceWith(newSection)
newButton.focus(); // always causes reflow; but fast because it's only one element
// store all other nodes after focus
newSection.append(...dummies)
}
window.renderPage = renderPage
我有一个项目负责管理元素的渲染,但我 运行 遇到性能问题,替换元素然后专注于之前关注的内容。
下面是复制性能问题的最小示例:
const renderPage = () => {
// get the old section element
const oldSection = document.querySelector('section')
// create a new section element (we'll replaceWith later)
const newSection = document.createElement('section')
// create the render button
const newButton = document.createElement('button')
newButton.innerHTML = 'Render Page'
newButton.onclick = renderPage
newSection.appendChild(newButton)
// create a bunch of elements
const dummyDivs = [...new Array(100000)].forEach(() => {
const dummy = document.createElement('div')
dummy.innerHTML = 'dummy'
newSection.appendChild(dummy)
})
// replace the old page with the new one (causes forced reflow)
oldSection.replaceWith(newSection)
// reattach focus on the button (causes forced reflow)
newButton.focus()
}
window.renderPage = renderPage
<section>
<button onclick="renderPage()">Render</button>
</section>
当 运行 在本地时,我在 Chrome/Edge 的性能报告中看到以下内容
replaceWith
和focus
都在触发强制回流。有没有办法对这些操作进行批处理或分组,以便只发生一次回流?我意识到根本没有办法真正解决这种情况,但如果我可以对它们进行批处理,我认为这可能会提高我的表现。
确实,焦点总是导致回流:What forces layout / reflow
所以您可以做的是通过独立插入新按钮来减少回流时间,启动焦点,然后您可以附加其他子按钮:
工作示例:Example
const renderPage = () => {
// get the old section element
const oldSection = document.querySelector('section')
// create a new section element (we'll replaceWith later)
const newSection = document.createElement('section')
// create the render button
const newButton = document.createElement('button')
newButton.innerHTML = 'Render Page'
newButton.onclick = renderPage
newSection.appendChild(newButton)
// create a bunch of elements
const dummies = []; // store in seperate array
const dummyDivs = [...new Array(100000)].forEach(() => {
const dummy = document.createElement('div')
dummy.innerHTML = 'dummy';
dummies.push(dummy)
})
// insert new section only with new button
oldSection.replaceWith(newSection)
newButton.focus(); // always causes reflow; but fast because it's only one element
// store all other nodes after focus
newSection.append(...dummies)
}
window.renderPage = renderPage