在一次操作中更改元素属性(数据集) - 避免回流
Posted
技术标签:
【中文标题】在一次操作中更改元素属性(数据集) - 避免回流【英文标题】:Change element attributes (datasets) in one operation - avoid Reflows 【发布时间】:2021-11-22 17:06:57 【问题描述】:我试图避免CSS Reflows
,
通常DocumentFragment
足以满足我的需求。
当我修改/添加/删除datasets
时,我有一些案例,
问题是每个dataset
都需要一个导致回流的操作..
element.dataset
是一个只读对象,所以我想知道如何在这个例子中只用一个回流而不是 3 个来做到这一点?
element.dataset.a='1'
delete element.b
element.dataset.c='2'
完全替换元素是实现此目的的唯一方法吗?
【问题讨论】:
在观看了here 关于 CSS 回流的视频后,我不确定他们甚至不知道他们在说什么。根据我的编程逻辑,我很确定 DOM 是循环的,所以任何更具体的内容实际上都会阻止绘制 DOM 树。太多的动画或变换可能是一个问题。DocumentFragment
仅用于将内容附加到document
。我不建议使用它,因为在将事件附加到 DOM 之前,您不能将事件附加到 DocumentFragment
中的节点。
【参考方案1】:
更改元素的数据集不会导致同步回流。您可以在同一任务中多次执行此操作。
要测试某些东西是否会导致回流,您可以使用 CSS 过渡。 从已知状态开始,然后设置中间状态,触发应该导致回流的原因,最后恢复原始状态。 如果测试的操作确实触发了重排,那么将发生从中间状态到最终状态的新转换。如果没有发生回流,则不会发生转换。
function testReflow(func)
return new Promise( (res, rej) =>
const elem = document.querySelector(".reflow-tester");
// set "intermediary" values
elem.style.opacity = 1;
elem.style.transition = "none";
try func(elem); catch(err) rej(err)
elem.style.opacity = 0;
elem.style.transition = "opacity 0.01s";
// if the tested func does trigger a reflow
// the transition will start from 1 to 0
// otherwise it won't happen (from 0 to 0)
elem.addEventListener("transitionstart", (evt) =>
res(true); // let the caller know the result
, once: true );
// if the transition didn't start in 100ms, it didn't cause a reflow
setTimeout(() => res(false), 100);
);
(async () =>
// wait 1s before executing the tests to be sure we're not in weird first paint
await new Promise((res) => setTimeout(res, 1000));
// first testing with a well known reflow trigger
const offsetWidth = await
testReflow((elem)=>elem.offsetWidth);
console.log("offsetWidth getter:", offsetWidth);
// now with dataset
const dataset = await testReflow((elem) =>
elem.dataset.foo = "bar";
elem.dataset.bar = "baz";
elem.dataset.baz = "bla";
);
console.log("dataset:", dataset);
)().catch(console.error);
.reflow-tester
opacity: 0;
<div class="reflow-tester">Tester</div>
【讨论】:
以上是关于在一次操作中更改元素属性(数据集) - 避免回流的主要内容,如果未能解决你的问题,请参考以下文章