先用 display: none/block + setinterval + data-index 搭最小可运行结构,重点解决 dom 选错、定时器未清理、图片错位三问题;html 必须规范嵌套,img 带宽高和 alt,初始仅首张显示,定时器需统一管理并加越界守卫。

别从 JS 动画或 Swiper 入手,先用 display: none + setInterval + data-index 搭出能跑的最小结构——90% 的初学者卡在 DOM 选不对、定时器没清理、图片堆叠错位这三处。
HTML 结构必须用 div.carousel 包住独立 img 标签
所有图片必须是 div.carousel 的直接子元素或统一放在一个子容器(如 div.carousel-images)里,不能散落在页面各处。否则 JS 找不到、CSS 控制不了。
-
img必须带alt和固定宽高(如width="600" height="400"),避免切换时布局抖动 - 别用
<picture></picture>或<source></source>,初学阶段响应式先关掉 - 导航按钮用
<button type="button" data-index="0"></button>,不用<a></a>或<span></span>,防止默认跳转或焦点干扰 - 初始状态:所有
img默认style="display: none;",第一张额外加style="display: block;"
display 切换比 transform 更适合起步
新手第一版轮播图,优先用 display: none/block 控制显隐,不是因为“简单”,而是它不触发重排(reflow)以外的副作用,调试时一眼能看出哪张在显示。
- 切图前必须先遍历所有
img设为display: none,再设目标项为block;顺序反了会导致多张同时显示 - 别用
visibility: hidden替代——它仍占布局空间,可能把容器撑高,导致上下跳动 - 如果容器高度不固定,
display切换会引发重排;此时给div.carousel加死高度(如height: 400px) - 动画效果(淡入/滑动)等逻辑跑通后再加,
transition要配opacity或transform,别碰left或margin
setInterval 必须配 clearInterval 和暂停逻辑
只写 setInterval(next, 3000) 是最常见崩点:用户点按钮后定时器还在跑,鼠标悬停时还在切,结果图片乱跳、索引错位、内存泄漏。
- 定义全局变量
let carouselTimer = null,每次调用setInterval前先clearInterval(carouselTimer) - 给
div.carousel绑mouseenter和mouseleave:进则clearInterval,出则重新setInterval - 所有手动操作(点按钮、点指示点)后都要调用重置函数,比如
resetTimer(),否则刚切到第2张,0.5秒后又跳到第3张 - 不要用
setTimeout递归模拟自动播放——不好统一清理,且易堆栈溢出
索引越界和循环取余是 JS 最容易漏的判断点
轮播图崩得最莫名其妙的时候,往往不是动画没动,而是 currentIndex 变成 -1 或 5(而只有 3 张图),后续所有 slides[currentIndex] 都是 undefined。
- 在
goToSlide(index)开头加守卫:if (index = slides.length) return; - 实现循环轮播时,别硬写
if (currentIndex === slides.length - 1) currentIndex = 0,改用取余:currentIndex = (currentIndex + 1) % slides.length - 左右按钮的
next()/prev()函数里,prev()要用(currentIndex - 1 + slides.length) % slides.length避免负数取余失效 - 所有 DOM 查询(如
document.querySelectorAll('.carousel img'))必须在DOMContentLoaded后执行,否则slides是空 NodeList
轮播图真正的复杂点不在“怎么动”,而在“什么时候不该动”:用户正在点、鼠标正悬停、JS 还没加载完、图片还没 onload……这些边界条件比动画本身更消耗调试时间。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











