Ric*_*ard 12 javascript css settimeout promise
请尝试运行以下代码段,然后单击该框。
const box = document.querySelector('.box')
box.addEventListener('click', e => {
if (!box.style.transform) {
box.style.transform = 'translateX(100px)'
new Promise(resolve => {
setTimeout(() => {
box.style.transition = 'none'
box.style.transform = ''
resolve('Transition complete')
}, 2000)
}).then(() => {
box.style.transition = ''
})
}
})Run Code Online (Sandbox Code Playgroud)
.box {
width: 100px;
height: 100px;
border-radius: 5px;
background-color: #121212;
transition: all 2s ease;
}Run Code Online (Sandbox Code Playgroud)
<div class = "box"></div>Run Code Online (Sandbox Code Playgroud)
我期望发生的事情:
Promise还会创建一个新的。里面说Promise,一个setTimeout函数设置为2秒setTimeout运行其回调函数并设置transition为无。这样做之后,setTimeout也恢复transform到它的原始值,从而使框出现在原始位置。transition框的值设置回其原始值但是,可以看出,运行时transition似乎没有该值none。我知道还有其他方法可以实现上述目标,例如使用关键帧和transitionend,但为什么会发生这种情况?transition只有在setTimeout完成回调后,我才显式地将返回值设置为原始值,从而解决了 Promise。
编辑
事件循环批处理样式更改。如果您在一行上更改元素的样式,浏览器不会立即显示该更改;它会等到下一个动画帧。这就是为什么,例如
elm.style.width = '10px';
elm.style.width = '100px';
Run Code Online (Sandbox Code Playgroud)
不会导致闪烁;浏览器只关心所有 Javascript 完成后设置的样式值。
渲染发生在所有 Javascript 完成后,包括微任务。将.then在microtask诺言的发生(如所有其他JavaScript已经完成,这将有效地立即运行,但之前别的-比如渲染-有机会来运行)。
你在做什么是你的设置transition属性''在microtask,浏览器已经开始呈现变化引起的之前style.transform = ''。
如果您在 a 之后requestAnimationFrame(将在下一次重绘之前运行)重置转换为空字符串,然后在 a 之后setTimeout(将在下一次重绘之后运行),它将按预期工作:
elm.style.width = '10px';
elm.style.width = '100px';
Run Code Online (Sandbox Code Playgroud)
const box = document.querySelector('.box')
box.addEventListener('click', e => {
if (!box.style.transform) {
box.style.transform = 'translateX(100px)'
setTimeout(() => {
box.style.transition = 'none'
box.style.transform = ''
// resolve('Transition complete')
requestAnimationFrame(() => {
setTimeout(() => {
box.style.transition = ''
});
});
}, 2000)
}
})Run Code Online (Sandbox Code Playgroud)
.box {
width: 100px;
height: 100px;
border-radius: 5px;
background-color: #121212;
transition: all 2s ease;
}Run Code Online (Sandbox Code Playgroud)