在一次操作中更改元素属性(数据集)-避免Reflows



我试图避免CSS Reflows,通常DocumentFragment就足够满足我的需要了。

我有情况下,当我修改/添加/删除datasets,问题是每个dataset需要一个导致回流的操作…

element.dataset是一个只读对象,所以我想知道我怎么能做到只有一个流,而不是3在这个例子中?

element.dataset.a='1'
delete element.b
element.dataset.c='2'

完全替换元素是实现这一目标的唯一方法吗?

更改元素的数据集不会导致同步流。在同一任务中,你可以想做多少次都可以。

要测试某些东西是否会导致回流,你可以使用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>