javascript - MutationObserver 知道何时在 HTML 中计算和渲染样式
问题描述
所以我创造了一些东西,我需要能够在有和没有过渡的情况下转换一些元素。
假设我必须在没有过渡的情况下转换某些东西,然后我当然首先从元素中删除转换参数(如果有的话),每当我知道转换样式消失时,我想转换元素。也许在那之后我想再次转换元素,但这次有一些过渡。所以首先,我添加了过渡,只要准备好了,我就会变换元素。
我创建了一个函数“setStyle”,它应该处理给定元素的样式设置,然后在该样式实际添加到视图时解析。我试图在 MutationObserver 的帮助下这样做。但是我显然误解了这点,或者 MutationObserver 的用例。
我创建了一个带有函数“setStyle”的简单 CodePen,我在其中演示了我首先使用该函数来设置转换样式属性,并且由于尚未添加转换属性,因此不应该进行转换。在我添加了转换属性之后,我添加了转换属性,但在这个代码示例中,看起来这两个属性是同时应用的。
为什么我不只使用“setTimeout”?“setTimeout”不是保证,我想做一些适用于任何 Web API 的事情。
https://codepen.io/herman-jansson/pen/NWNKWXL
<button id="start">Start</button>
<div id="div">
</div>
var elem = document.getElementById('div');
var setStyle = (element, style, value) => {
return new Promise(resolve => {
const observer = new MutationObserver((mutations) => {
if(
document.contains(element)
&&
mutations.some((mutation) => !!mutation.attributeName)
) {
// style should be added here, but most likely not calculated since
// its not working
observer.disconnect();
resolve();
}
})
observer.observe(element, { attributes: true, attributeFilter: ["style"]});
element.style[style] = value;
});
}
document.getElementById('reset').addEventListener('click', () => {
setStyle(elem, 'transform', 'translateX(-50%)').then(() => {
setStyle(elem, 'transition', 'transform 1s ease-in-out')
});
});
解决方案
虽然属性确实style
在两个离散的步骤中更新(如通过向 MutationObserver
您MutationObserver
只是看到属性已更新(但如果渲染引擎应用了更改,则不会)并立即解决。当渲染引擎开始对style
更改采取行动时,这两项更改都已完成,并被视为同一更新的一部分。
style
一种解决方案是在两个属性更新之间自行触发回流。(这通常不是您想要做的事情,因为它会使页面的响应速度降低,因此应慎重应用。)通常,(直接或间接)读取元素的计算尺寸或位置会导致重排. 这个要点列出了一些已知会导致立即回流的属性和函数。
总而言之,添加一个类似element.offsetLeft;
这样的行以便在两个样式更新之间执行它可能看起来什么都不做,但会导致回流作为副作用。这反过来会导致渲染引擎将这两个style
更改视为单独的更新。
我相信您甚至可以删除该setStyle
功能并使用:
elem.style.transform = 'translateX(-50%)';
elem.offsetLeft;
elem.style.transition = 'transform 1s ease-in-out';
推荐阅读
- debugging - 调试颤振时如何打印出对象的整个私有值字符串
- css - Rvest,html_nodes 返回空列表和字符串,使用网站
- kubernetes - 如何从 kubernetes API 或其他方式获取 istio 对象状态(例如虚拟服务运行状态)?
- android - Koin Android:注入存储库时出现org.koin.error.NoBeanDefFoundException
- powershell - 如何将 PowerShell 模式从约束模式更改为全语言模式?
- sas - 为 SAS 中的所有观察值保留一个值
- php - 使用变量时php错误数组到字符串转换
- ios - iOS - AudioToolbox 内存泄漏
- c - 数组如何终止?
- php - 如何在显示页面中删除我的消息代码中的接收者姓名和我们的消息?