Transitionend event and eventloop



解释我的问题的最好方法是下面两个演示:

就是它们:

演示1(在chrome中正常工作,在firefox中不起作用)

let handler = function () {
block.classList.add("visible");
requestAnimationFrame(() => block.classList.add("move"));
block.addEventListener(
"transitionend",
() => {
console.log("style is removed");
this.addEventListener("click", handler, { once: true });
block.classList.remove("move");
},
{ once: true }
);
};
btn.addEventListener("click", handler, { once: true });
.main {
display: none;
width: 100px;
height: 100px;
background: red;
transition: all 5.5s ease;
}
.visible {
display: block;
}
.move {
transform: translateX(100px);
background: blue;
}
<div id="block" class="main"></div>
<button id="btn">Animate</button>

演示2(工作不正确)

let handler = function () {
block.classList.add("visible");
block.classList.add("move");
block.addEventListener(
"transitionend",
() => {
console.log("style is removed");
this.addEventListener("click", handler, { once: true });
block.classList.remove("move");
},
{ once: true }
);
};
btn.addEventListener("click", handler, { once: true });
.main {
display: none;
width: 100px;
height: 100px;
background: red;
transition: all 5.5s ease;
}
.visible {
display: block;
}
.move {
transform: translateX(100px);
background: blue;
}
<div id="block" class="main"></div>
<button id="btn">Animate</button>

我将快速强调两个演示之间的差异:

  1. 第一个演示有requestAnimationFrame

  1. <div>block有class "visible"在第一个演示中启动点击处理程序之前
  2. 在click处理程序中,它有用于添加类"visible"在第二次演示

所以主要问题是:为什么第二个演示没有触发transitionend事件,为什么我没有看到过渡?


额外的演示

let handler = function () {
alert(1);
block.classList.add("visible");
alert(2);
setTimeout(() => {
alert(4);
block.classList.add("move");
alert(5);
});
block.addEventListener(
"transitionend",
() => {
console.log("style is removed");
this.addEventListener("click", handler, { once: true });
block.classList.remove("move");
},
{ once: true }
);
alert(3);
};
btn.addEventListener("click", handler, { once: true });
.main {
display: none;
width: 100px;
height: 100px;
background: red;
transition: all 5.5s ease;
}
.visible {
display: block;
}
.move {
transform: translateX(100px);
background: blue;
}
<div id="block" class="main"></div>
<button id="btn">Animate</button>

在chrome和firefox中检查它,似乎是代码的某些部分调用了重绘,如果不是,纠正我并解释为什么。

这里有几件事,你首先写的是block.classList.add("visible");,我认为主要原因是你故意遗漏了这个class="main visible",因为你在代码中像class="main"一样写它。

你实际上需要使用css样式技术,即使用none来隐藏div和block来显示它。这是我首先隐藏它的.visible { display: none; },然后显示它,我使用document.getElementById("block").style.display = "block";。我添加了一个小延迟,给它一个时间来完成显示,然后开始动画工作,但不工作,如果你删除延迟。

let handler = function () {
//block.classList.add("visible");
document.getElementById("block").style.display = "block"; 
setTimeout(() => { block.classList.add("move"); }, 300);
//block.classList.add("move");
block.addEventListener(
"transitionend",
() => {
console.log("style is removed");
this.addEventListener("click", handler, { once: true });
block.classList.remove("move");
},
{ once: true }
);
};
btn.addEventListener("click", handler, { once: true });
.main {
display: none;
width: 100px;
height: 100px;
background: red;
transition: all 5.5s ease;
}
.visible {
display: none;
}
.move {
transform: translateX(100px);
background: blue;
}
<div id="block" class="main visible"></div>
<button id="btn">Animate</button>

所以要回答为什么它没有发射,这是由于我在上面解释的原因。