轮播图切换时transitionend事件监听器未触发及幻灯片中途消失问题
问题原因
- 变量捕获错误:你绑定
transitionend事件时使用的是全局变量currentSlide,事件是异步触发的,等事件回调执行时,currentSlide已经被后续的自增/重置逻辑修改了,回调里操作的根本不是你要处理的那张幻灯片。 - 重复绑定事件:每次轮播触发你都会给幻灯片新增
transitionend监听,没有移除旧的监听,多次轮播后同一个元素上会绑定大量重复的事件回调,执行逻辑完全混乱。 - 属性取值错误:
visibility的隐藏值是hidden,不是none(none是display属性的取值),错误的赋值会导致样式生效异常。 - 复位逻辑多余过渡:你把幻灯片移回起始位置时,没有临时关闭过渡效果,会导致复位也触发过渡动画,内层重复绑定的
transitionend进一步加剧逻辑混乱。
解决方法
调整逻辑如下:
- 绑定事件前先缓存当前的幻灯片序号,避免全局变量变更的影响
- 使用具名事件回调,绑定前先移除旧的监听,避免重复绑定
- 修正
visibility的取值 - 复位幻灯片位置时临时关闭过渡,实现瞬间复位,不需要额外的内层监听
- 增加属性判断,只有
left属性的过渡结束才触发回调,避免其他属性过渡的干扰
修改后的关键代码示例:
function startSlideshow(){ setSlidesPosition(); setInterval(() => { if (firstTimeLoaded){ currentSlide = 0; firstTimeLoaded = false; } // 缓存当前要处理的幻灯片序号和元素 const activeIndex = currentSlide; const activeSlide = slides[activeIndex]; // 展示下一张幻灯片 if (currentSlide === (numberOfSlides - 1)){ slides[0].style[animationType] = displayValue; } else { slides[currentSlide + 1].style[animationType] = displayValue; } // 当前幻灯片移向结束位置 activeSlide.style[animationType] = endValue; // 先移除之前绑定的旧回调,避免重复触发 if (activeSlide.transitionCallback) { activeSlide.removeEventListener('transitionend', activeSlide.transitionCallback); } // 定义本次过渡结束的回调 activeSlide.transitionCallback = (e) => { // 只处理left属性的过渡结束事件 if (e.propertyName !== animationType) return; // 隐藏幻灯片 activeSlide.style.visibility = "hidden"; // 临时关闭过渡,实现瞬间复位 const originalTransition = activeSlide.style.transition; activeSlide.style.transition = 'none'; // 回到起始位置 activeSlide.style[animationType] = startValue; // 强制浏览器重绘,确保复位样式生效后再恢复过渡 void activeSlide.offsetWidth; // 恢复过渡和可见性 activeSlide.style.transition = originalTransition; activeSlide.style.visibility = "visible"; // 回调执行完移除自身 activeSlide.removeEventListener('transitionend', activeSlide.transitionCallback); delete activeSlide.transitionCallback; } activeSlide.addEventListener('transitionend', activeSlide.transitionCallback); // 更新当前幻灯片序号 if (currentSlide === (numberOfSlides - 1)){ currentSlide = 0; setSlidesPosition(); } else { currentSlide++; } }, duration); }
内容的提问来源于stack exchange,提问作者killerprince182
相关产品推荐
相关产品推荐

