## 场景与目标
- 在长列表与图片密集页面中使用可见性检测触发懒加载,降低首屏体积与网络并发,提升 LCP 与滚动流畅度。
## 关键参数与已验证建议
- `root`: 默认视窗即可;如在局部滚动容器中使用,需设定该容器作为根。
- `rootMargin`: 预加载窗口,推荐 `50px–200px`;图片懒加载常取 `200px` 以避免用户滚动到位时仍在等待。
- `threshold`: 曝光比例数组,图片懒加载建议 `0 或 [0, 0.2]`;模块加载可取 `[0.1, 0.25]`,减少抖动与频繁触发。
## 实现代码(图片懒加载)
// utils/lazy-image.js
export function setupLazyImages({ root = null, rootMargin = '200px', threshold = [0] } = {}) {
const imgs = Array.from(document.querySelectorAll('img[data-src]'));
if (!('IntersectionObserver' in window)) {
// 兼容降级:直接加载或使用滚动节流策略
imgs.forEach(img => { img.src = img.getAttribute('data-src'); });
return () => {};
}
const io = new IntersectionObserver((entries) => {
for (const e of entries) {
if (e.isIntersecting) {
const img = e.target;
img.src = img.getAttribute('data-src');
img.removeAttribute('data-src');
io.unobserve(img);
}
}
}, { root, rootMargin, threshold });
imgs.forEach(img => io.observe(img));
return () => io.disconnect();
}
## 模块懒加载(按需渲染/加载)
// utils/lazy-module.js
export function lazyRender(selector, render, { root = null, rootMargin = '100px', threshold = [0.1, 0.25] } = {}) {
const els = Array.from(document.querySelectorAll(selector));
if (!('IntersectionObserver' in window)) {
els.forEach(el => render(el));
return () => {};
}
const io = new IntersectionObserver((entries) => {
for (const e of entries) {
if (e.intersectionRatio >= 0.1) {
const el = e.target;
render(el);
io.unobserve(el);
}
}
}, { root, rootMargin, threshold });
els.forEach(el => io.observe(el));
return () => io.disconnect();
}
## 验证方法与注意事项
- 参数采样:使用 `PerformanceObserver` 与 `web-vitals` 记录 LCP/FID/CLS;观察不同 `rootMargin` 与 `threshold` 对首屏与滚动的影响。
- 图片加载策略:结合 `loading="lazy"` 与 `decode()`;IO 触发用于早加载、`lazy` 属性作为兜底。
- 对于低端设备与弱网环境,`rootMargin` 适度加大以降低滚动白屏概率;同时限制并发请求数(如 4–6)。
- 兼容性:旧浏览器可降级为滚动监听 + 节流方案(参考节流文章实现)。
## 总结
- IntersectionObserver 在懒加载场景中提供更稳定、低开销的可见性检测;合理设置 `rootMargin` 与 `threshold` 可在用户体验与资源占用间取得平衡。
- 上述参数区间在实际页面中已验证,适合作为默认策略并在特定页面中进一步调优。

发表评论 取消回复