Vue项目中使用IntersectionObserver实现加载进度条导致滚动卡顿怎么办?
在Vue项目里想用IntersectionObserver检测关键资源加载进度,然后发现滚动时页面卡顿,特别是资源较多时更明显。我尝试给每个资源元素添加了观察器,然后在回调里计算总进度:
const observer = new IntersectionObserver((entries) => {
let loaded = 0;
entries.forEach(entry => {
if (entry.isIntersecting) {
loaded += entry.target.dataset.size;
updateProgress(loaded / totalSize);
}
});
}, { rootMargin: '0px', threshold: 1.0 });
resources.forEach(el => observer.observe(el));
但滚动到密集元素区域时,fps会突然掉到20多。试过把计算逻辑抽到requestAnimationFrame里也没好转,是不是观察器实例太多导致的?有没有更高效的方式实现加载进度同步?
其实不需要为每个资源单独创建 Observer,可以用一个共享实例来观察所有元素,这才是标准做法。另外你现在的 threshold 是 1.0,意味着必须完全进入视口才触发,这会导致体验延迟,也不利于平滑更新进度。
你可以这样改:
关键点:
- 全局一个 Observer 实例就够了,别每个元素搞一个
- 用 Set 记录已见过的元素,避免重复计算
- rootMargin 加载缓冲区,threshold 调低一点让触发更早更平滑
- 把 updateProgress 放进 rAF,避免高频更新 DOM
这样更清晰,也能把 FPS 拉回来。如果还觉得卡,可以把 updateProgress 做节流,比如每 100ms 最多更新一次,用户也感知不到差异。