你在做「企业级低代码平台」时,客户把 200+ 微应用一次性嵌进门户首页。
浏览器自带的进度条只认主文档,微应用懒加载的 JS/CSS/图片它一概不管,用户盯着 100 % 的进度条却白屏 3 秒,投诉直接拉满。
于是,你撸了一条 完全受控的自定义加载进度条,从 0 % 到 100 % 与真实资源一一对应,投诉率当天掉到 0。
方案:15 分钟搭一条"真·进度条"
1. 骨架 HTML(30 秒)
html
<!-- index.html -->
<div id="progress-bar">
<div class="fill"></div>
<span class="text">0%</span>
</div>
2. 核心 JS(5 分钟)
js
// progress.js
class Loader {
#total = 0
#loaded = 0
#fill = document.querySelector('.fill')
#text = document.querySelector('.text')
add(url) {
this.#total++
fetch(url).then(() => {
this.#loaded++
this.#render()
})
}
#render() {
const p = Math.round((this.#loaded / this.#total) * 100)
this.#fill.style.transform = `scaleX(${p / 100})`
this.#text.textContent = `${p}%`
if (p === 100) this.#fill.parentElement.remove()
}
}
window.loader = new Loader()
逐行解析
add
把每一个资源注册进来,用原生fetch
自带 Promise 跟踪完成。scaleX
做宽度动画,GPU 加速不掉帧。- 100 % 时自毁 DOM,避免污染全局。
3. 使用姿势(1 分钟)
html
<script type="module">
import './progress.js'
// 🔍 业务代码里显式注册资源
loader.add('/static/chunk-a.js')
loader.add('/static/theme.css')
loader.add('/static/logo.png')
</script>
原理深挖:三层视角看"真进度"
层级 | 表面用法 | 底层机制 | 设计哲学 |
---|---|---|---|
资源层 | fetch 监听 |
HTTP 缓存协商 + TCP 多路复用 | 用浏览器能力,不重复造轮子 |
渲染层 | scaleX + requestAnimationFrame |
合成层动画,60 FPS | 视觉反馈优先,主线程不阻塞 |
生命周期 | 100 % 自毁 | 垃圾回收自动清理 | 用完即走,零副作用 |
扩展:3 个真实业务变体
1. Vue3 组合式封装(微应用场景)
ts
// useProgress.ts
import { ref, computed } from 'vue'
export function useProgress() {
const total = ref(0), loaded = ref(0)
const percent = computed(() => (loaded.value / total.value) * 100 || 0)
const add = (url: string) => {
total.value++
fetch(url).finally(() => loaded.value++)
}
return { percent, add }
}
在
<Suspense>
的@pending
里调用add
,进度与组件懒加载天然同步。
2. 大文件切片上传(断点续传)
js
// 伪代码
chunks.forEach((chunk, i) => {
loader.add(`/upload?index=${i}`) // 每个切片算 1 个进度单位
})
3. Service Worker 离线缓存
js
// sw.js
self.addEventListener('install', e => {
const urls = [...] // 预缓存列表
e.waitUntil(
caches.open('v1').then(cache =>
Promise.all(
urls.map(u => fetch(u).then(r => cache.put(u, r)))
)
)
)
// 向主线程 postMessage 更新进度
})
一键复用片段
css
/* 进度条样式,直接拷 */
#progress-bar {
position: fixed; top: 0; left: 0; right: 0; height: 3px;
background: rgba(0,0,0,.1); z-index: 9999;
}
.fill {
height: 100%; background: #0076ff;
transform-origin: left; transition: transform .3s ease;
}
.text {
position: absolute; top: 4px; right: 8px;
font-size: 12px; color: #0076ff;
}
小结
浏览器那条"假进度"只能骗自己,自定义进度条才是用户信任的起点。
把上面的 30 行代码丢进任何项目,3 分钟就能让白屏时间变成"可控的等待"。
下次老板再说"体验优化",你就可以把这篇文章甩给他,然后安心下班。