Estoy tratando de evitar CSS Reflows , por lo general, DocumentFragment es suficiente para mis necesidades.
Tengo casos en los que modifico/agrego/elimino conjuntos de datasets . El problema es que cada conjunto de dataset requiere una operación que provoca el reflujo.
element.dataset es un objeto de solo lectura, así que me preguntaba cómo puedo hacerlo con un solo reflujo en lugar de 3 en este ejemplo.
element.dataset.a='1' delete element.b element.dataset.c='2'¿Reemplazar el elemento por completo es la única forma de lograr esto?
Cambiar el conjunto de datos de un elemento no provocará un reflujo síncrono. Puedes hacerlo tantas veces como quieras durante la misma tarea.
Para probar si algo provoca un reflujo o no, puede usar una transición CSS.
Pasar de un estado conocido, luego establecer un estado intermedio, desencadenar lo que debería causar el reflujo y finalmente restablecer el estado original.
Si la acción probada desencadenó un reflujo, ocurrirá una nueva transición del estado intermedio al final. Si no ocurrió ningún reflujo, entonces no ocurrirá ninguna transición.
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>