前言
首页轮播看起来只是定时换背景,但真正稳定的实现还要处理图片加载失败、淡入时的空白、后台标签页暂停绘制和浏览器缓存。本篇重点解释这些容易踩坑的细节。
一、配置、构建和浏览器三层分工
_config.butterfly.yml |
把图片列表放进配置文件后,日常换图不需要编辑 JavaScript。
二、怎样配置轮播
home_banner: |
interval 使用毫秒,5000 表示 5 秒。脚本还会把过小的值限制在 3 秒以上:
const interval = Math.max( |
太快的切换会让图片还没看清就消失,也会增加网络和绘制压力。
三、为什么仍然保留 index_img
轮播依赖 JavaScript。如果脚本尚未执行或用户禁用了脚本,首页不能出现纯色空白。因此仍为 Butterfly 配置静态兜底图:
index_img: https://example.com/fallback.jpg |
轮播初始化成功后再清除原背景:
header.style.backgroundImage = 'none' |
这叫“渐进增强”:基础页面先可用,JavaScript 只在其上增加能力。
四、构建时怎样把 YAML 交给浏览器
浏览器不能直接读取服务器上的 _config.butterfly.yml。Hexo 过滤器把必要配置写进 <head>:
const config = { |
只传给前端真正需要的两个字段,避免把整个主题配置暴露到页面。
五、为什么不用一个元素直接换 background-image
如果只对一个元素执行:
element.style.backgroundImage = nextUrl |
浏览器会立即替换图片。CSS 很难同时保留上一张并让下一张淡入,图片没加载完时还可能短暂显示背景色。
这里采用“双层交叉淡入”:
旧图 opacity: 1 → 0 |
每张图都是绝对定位的独立元素:
.home-banner-slide { |
六、预加载怎样避免坏图造成空白
切换前先创建 Image 对象:
const preload = url => new Promise(resolve => { |
showNext() 会依次尝试后续图片:
let attempts = 0 |
某张图片失效时自动跳过;所有图片都失败时保留当前画面,等待下一轮,而不是把可用旧图删掉。
七、“先变蓝再显示下一张”是怎样产生的
淡入淡出的关键顺序是:
- 保存当前活动层;
- 创建并插入下一层;
- 确保浏览器先绘制下一层的
opacity: 0; - 给下一层添加
is-active; - 再让旧层淡出;
- 过渡完成后删除旧层。
正确代码:
const previousSlide = activeSlide |
早期问题出在定时器中引用了后来已经被修改的 activeSlide。变量更新后,定时器可能删除新图而不是旧图,于是页面只剩头部底色。
把旧层立即保存为 previousSlide,定时器闭包就会一直指向正确元素。
八、void nextSlide.offsetWidth 有什么作用
浏览器会批量合并 DOM 和样式修改。如果刚插入元素就立刻添加 is-active,它可能只绘制最终的 opacity: 1,中间没有可过渡的起点。
读取 offsetWidth 会迫使浏览器先完成一次布局:
void nextSlide.offsetWidth |
此时浏览器已经确认元素初始状态是 opacity: 0,下一行改为 1 才会触发过渡。
最初尝试过 requestAnimationFrame(),但后台标签页会降低或暂停动画帧调度,恢复页面时容易出现状态不同步。强制布局在这里更可控。
九、后台标签页怎样处理
浏览器标签页不可见时不必继续切图:
if (document.hidden) return scheduleNext() |
这里没有停止整个轮播,也没有一次性补做错过的切换,只是把下一次检查推迟一个间隔。用户回到页面后,从当前图片继续,避免瞬间连续跳过多张。
十、层级为什么要单独设置
轮播层放在最底层,导航和首页文字放在上方:
#page-header.full_page { |
isolation: isolate 创建独立层叠上下文,避免负层级跑到整个页面背后;pointer-events: none 保证背景不会挡住菜单点击。
十一、为什么代码改了,线上仍像没改
浏览器和 Nginx 可能长期缓存静态 JavaScript。即使服务器文件已经更新,旧标签页仍可能使用缓存版本。
解决方法是在资源地址后增加版本号:
inject: |
文件内容变化时同步更新 v=,浏览器会把它视为新地址重新请求。版本号不参与服务器文件查找,只用于区分缓存键。
十二、维护入口
- 添加、删除图片和修改间隔:
_config.butterfly.yml的home_banner - 配置注入:
scripts/home-banner-config.js - 图片预加载和切换:
source/js/home-banner-carousel.js - 淡入时长与页面层级:
source/css/custom.css - 更新脚本后刷新缓存:修改注入 URL 的
?v=
结语
一个稳定轮播依赖的不是定时器,而是“下一张先加载成功、旧层保留到过渡完成、后台页面不补帧、资源更新能绕过缓存”这四个条件。






