如何在一个transitionend事件触发后触发另一个?触发异常排查
问题解决:transitionend事件触发异常的修复
问题根源
- 第一个transitionend触发过早:未过滤触发事件的目标属性,若浏览器对transform过渡的子属性单独触发事件,会导致逻辑提前执行;同时事件未做单次绑定,可能重复触发。
- 第二个transitionend完全未触发:设置
display: none后,元素会被移出渲染树,后续的transform属性修改不会触发过渡效果,自然不会触发transitionend。
修正后的代码
JavaScript
const nameBox = document.getElementById("nameBox"); // 第一步:触发向左移出窗口的过渡 nameBox.style.transform = "translateX(-100%)"; // 监听第一次过渡结束,确保只执行一次 nameBox.addEventListener("transitionend", function firstMoveEnd(event) { // 仅处理transform属性的过渡完成事件 if (event.propertyName !== "transform") return; // 移除当前监听,避免重复触发 nameBox.removeEventListener("transitionend", firstMoveEnd); // 临时关闭过渡,直接将元素定位到右侧窗口外(用户不可见) nameBox.style.transition = "none"; nameBox.style.transform = "translateX(100%)"; // 强制浏览器重绘,让transform立即生效 void nameBox.offsetWidth; // 隐藏元素 nameBox.style.display = "none"; // 这里可根据需求调整延迟,直接执行也可 setTimeout(() => { // 第二步:显示元素并触发返回窗口的过渡 nameBox.style.display = "inline-block"; // 恢复过渡配置 nameBox.style.transition = "transform 1.5s ease-in-out"; nameBox.style.transform = "translateX(0%)"; // 可选:监听返回完成事件 nameBox.addEventListener("transitionend", function backMoveEnd(event) { if (event.propertyName !== "transform") return; nameBox.removeEventListener("transitionend", backMoveEnd); console.log("元素已回到窗口内"); }, { once: true }); }, 500); }, { once: true });
CSS(优化过渡目标属性)
#nameBox{ margin: 5px; width: 95%; display: inline-block; text-align: center; background: #231123; color: white; font-size: 20px; white-space: nowrap; transition: transform 1.5s ease-in-out; /* 明确只过渡transform属性,减少不必要的事件触发 */ }
关键修复点
- 过滤事件属性:通过
event.propertyName判断只处理transform的过渡完成,避免无关属性触发逻辑。 - 单次事件绑定:使用
{ once: true }或主动移除监听,确保每个过渡阶段的事件只执行一次。 - 避免display:none打断过渡:第一次过渡完成后,先关闭过渡直接定位元素到右侧,再隐藏,跳过无效的过渡监听。
- 强制重绘:修改过渡状态后通过
void element.offsetWidth强制浏览器更新渲染,确保样式立即生效。
内容的提问来源于stack exchange,提问作者Batcha
相关产品推荐
相关产品推荐

