gpt4 book ai didi

javascript - setTimeout(fn,0) 在应用样式之前触发

转载 作者:行者123 更新时间:2023-11-29 15:22:54 26 4
gpt4 key购买 nike

当我想放弃执行我的 javascript 并允许浏览器在我继续之前应用样式等时,我倾向于使用 setTimeout 的常用技术,延迟 0 在事件循环结束时有一个回调排队。但是,我遇到了这样一种情况,它似乎无法可靠地工作。

在下面的代码片段中,我有一个 active 类,它向 chaser 元素应用过渡。

当我将鼠标悬停在目标 div 上时,我想从 chaser 元素中删除 active 类,将 chaser 移动到一个新的位置,然后重新应用 active 类。效果应该是 o 应该立即消失,然后淡入其新位置。相反,opacitytop 都应用了过渡,因此 o 幻灯片 从一个位置到另一个位置,< em>大部分时间。

如果我将内部超时的延迟增加到 10,它就会开始按照我最初的预期运行。如果我将它设置为 5,那么它有时会,有时不会。

我原以为任何 setTimeout 都会对我的回调进行排队,直到应用样式更新之后,但这里存在明显的竞争条件。我错过了什么吗?有没有办法保证更新的顺序?

我在 macOS 和 Windows 上使用 Chrome 56,尚未测试其他浏览器。

(我知道我可以通过其他方式实现这一点,例如仅将过渡应用于 opacity 属性 - 请将此视为一个人为的示例,以演示有关订购样式更新的特定问题)。

var targets = document.querySelectorAll('.target');
var chaser = document.querySelector('#chaser');
for (var i = 0; i < targets.length; i++) {
targets[i].addEventListener('mouseenter', function(event) {
chaser.className = '';
setTimeout(function() {
// at this point, I'm expecting no transition
// to be active on the element
chaser.style.top = event.target.offsetTop + "px";

setTimeout(function() {
// at this point, I'm expecting the element to
// have finished moving to its new position

chaser.className = 'active';
}, 0);
}, 0);
});
}
#chaser {
position: absolute;
opacity: 0;
}
#chaser.active {
transition: all 1s;
opacity: 1;
}
.target {
height: 30px;
width: 30px;
margin: 10px;
background: #ddd;
}
<div id="chaser">o</div>
<div class="target">x</div>
<div class="target">x</div>
<div class="target">x</div>
<div class="target">x</div>
<div class="target">x</div>

最佳答案

在执行任何其他操作之前,您需要监听的是 transitionend 事件。您可以阅读 MDN about transitionend event .顺便说一句,永远不要使用 setTimeout 来保证时间。

编辑:这是在 OP 澄清后供引用。每当元素发生样式更改时,都会发生回流和/或重绘。你可以read more about them here .如果第二次 setTimeout 在第一次回流之前运行,那么您将获得滑动效果。之所以10ms会达到预期的效果,是因为offsetTop属性调整后添加了.active类(导致transition属性在元素更改为 offsetTop 后应用)。通常,有 60fps(即:每帧约 16 毫秒),这意味着在应用新样式之前,您有一个 16 毫秒的窗口来做任何事情。这就是为什么 5 毫秒的小延迟有时会导致不同的结果。

TL:DR - 浏览器每 16 毫秒询问 JS 和 CSS 是否有任何更新,并计算要绘制的内容。如果您错过了 16 毫秒的窗口,您可能会得到完全不同的结果。

关于javascript - setTimeout(fn,0) 在应用样式之前触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42229156/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com