transitionend事件会多次触发,因每个参与过渡的css属性(如transform、opacity)都会独立触发一次;需用event.propertyname过滤或{once:true}控制,且不可与animationend混用。

transitionend 事件不是“动画播完就稳稳触发一次”的保险开关,它容易重复、漏触、兼容失灵——直接绑 addEventListener('transitionend', handler) 很大概率出问题。
为什么 transitionend 会触发多次?
只要一个元素的多个 CSS 属性同时参与过渡(比如 transform、opacity、width),每个属性变化完成都会独立触发一次 transitionend。例如:
element.style.transition = 'transform 0.3s, opacity 0.3s, width 0.3s';
这种写法会让事件最多触发 3 次,哪怕你只关心 transform 是否结束。
- 用
event.propertyName过滤目标属性:只在if (event.propertyName === 'transform') { ... }里执行逻辑 - 更稳妥的做法是加
{ once: true }配置,避免后续重复绑定导致叠加触发 - 别依赖
all或省略transition-property,显式声明要过渡的属性能减少意外触发
transitionend 不触发的常见原因
最典型的是:元素从 display: none 切到 block 后立刻加 class 触发过渡,但 transitionend 完全不响——因为浏览器没来得及渲染初始状态,过渡被跳过。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 必须确保元素已挂载且可见(
getComputedStyle(el).display !== 'none')再施加过渡样式 - 必要时手动强制重排(reflow):读取
el.offsetHeight或el.getBoundingClientRect(),让浏览器同步计算当前样式 -
opacity: 0 → 1能触发,但visibility: hidden → visible不会,因为它不触发过渡动画 - 起始值和结束值完全相等(如
left: 10px → 10px)也不会触发
如何写出兼容老浏览器的 transitionend 监听
截至 2026 年,transitionend 在现代浏览器中已统一为小写无前缀,但部分存量项目仍需支持旧版 Safari / Android Webview。
- 不要硬写
'webkitTransitionEnd'等前缀,而是动态检测:const transEnd = window.getComputedStyle(document.documentElement).transitionProperty ? 'transitionend' : 'webkitTransitionEnd' - 更健壮的做法是查
document.createElement('div').style上是否存在带前缀的 transition 属性名,再映射事件名(参考知识库中transitions对象) - 如果只支持 Chrome 80+、Firefox 70+、Safari 14+,可直接用
'transitionend',无需降级处理
transitionend 和 animationend 能混用吗?
不能。这是两个完全独立的机制:transitionend 只响应 transition 声明引发的渐变;animationend 只响应 @keyframes + animation 定义的帧动画。即使两者视觉效果一样,事件也不会交叉触发。
- 用
transition实现 hover 缩放?监听transitionend - 用
animation: bounce 0.5s实现弹跳?监听animationend - 误绑
animationend到过渡元素上,控制台不会报错,但回调永远不执行——这点特别容易被忽略
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










