1 使用 Intersection Observer API
什么是 Intersection Observer?
Intersection Observer API
是现代浏览器提供的一种接口,用于检测一个元素(目标元素)是否与视口(用户可见区域)或某个特定父容器交叉。
优点
- 不需要手动监听滚动事件,性能更优。
- 在用户接近目标区域时触发,比滚动事件更高效。
- 支持更复杂的触发条件设置,例如阈值(多少比例交叉时触发)。
实现方案
- 在页面底部放置一个标记元素(
sentinel
)。 - 使用
Intersection Observer
检测该标记元素是否进入视口。 - 触发加载更多内容的逻辑。
代码示例
<div id="content">
<!-- 已加载的内容 -->
</div>
<div id="sentinel"></div> <!-- 视口底部的标记 -->
// 创建观察器
const observer = new IntersectionObserver((entries) => {
// 检测目标元素是否可见
if (entries[0].isIntersecting) {
console.log('Sentinel 可见,加载更多内容');
loadMoreContent();
}
}, {
root: null, // 视口作为根容器
threshold: 0.1 // 当 10% 的 sentinel 进入视口时触发
});
// 开始观察标记元素
const sentinel = document.getElementById('sentinel');
observer.observe(sentinel);
function loadMoreContent() {
const container = document.getElementById('content');
for (let i = 0; i < 5; i++) {
const newItem = document.createElement('div');
newItem.textContent = `新内容项 ${Math.random()}`;
newItem.className = 'content-item';
container.appendChild(newItem);
}
}
参数详解
root
: 观察器的根容器,设置为null
表示视口。rootMargin
: 调整触发的边距,例如0px 0px -50px 0px
表示提前 50 像素触发。threshold
: 交叉比例阈值,范围为 0~1。
适用场景
- 高性能动态加载。
- 滚动事件监听存在性能瓶颈时。
2 懒加载图片
什么是图片懒加载?
图片懒加载指的是页面加载时不直接加载所有图片,而是等图片进入用户视口时再进行加载。这样可以优化页面性能,减少初始加载时间。
实现方案
- 图片元素使用占位符。
- 在图片元素上添加一个真实图片地址的属性(如
data-src
)。 - 当图片进入视口时,替换
src
属性以加载真实图片。
代码示例
<div id="content">
<img data-src="image1.jpg" alt="图片 1" class="lazy">
<img data-src="image2.jpg" alt="图片 2" class="lazy">
</div>
const images = document.querySelectorAll('.lazy');
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.getAttribute('data-src'); // 加载真实图片
img.classList.remove('lazy'); // 移除懒加载标记
observer.unobserve(img); // 停止观察
}
});
}, {
root: null, // 视口作为根容器
threshold: 0.1
});
// 开始观察所有懒加载图片
images.forEach((img) => observer.observe(img));
适用场景
- 有大量图片需要动态加载时。
- 优化首屏加载性能。
3 限制最大加载次数
为什么需要限制?
- 防止用户无限滚动。
- 限制服务器资源使用。
实现方案
记录已加载次数,在加载内容时检查是否超出最大限制。
代码示例
let loadCount = 0;
const maxLoadCount = 10; // 最大加载次数
function loadMoreContent() {
if (loadCount >= maxLoadCount) {
console.log('达到最大加载次数,不再加载');
return;
}
const container = document.getElementById('content');
for (let i = 0; i < 5; i++) {
const newItem = document.createElement('div');
newItem.textContent = `新内容项 ${Math.random()}`;
container.appendChild(newItem);
}
loadCount++;
console.log(`已加载次数: ${loadCount}`);
}
适用场景
- 限制用户行为。
- 防止无限滚动对系统性能的影响。
4 提供“返回顶部”按钮
为什么需要返回顶部按钮?
动态加载页面会让内容变长,用户需要方便地回到页面顶部。
实现方案
- 动态显示“返回顶部”按钮。
- 点击按钮时平滑滚动到顶部。
代码示例
<button id="backToTop" style="display: none;">返回顶部</button>
const backToTopButton = document.getElementById('backToTop');
// 监听滚动事件显示/隐藏按钮
window.addEventListener('scroll', () => {
if (window.scrollY > 300) {
backToTopButton.style.display = 'block';
} else {
backToTopButton.style.display = 'none';
}
});
// 返回顶部功能
backToTopButton.addEventListener('click', () => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
适用场景
- 动态内容增加时。
- 提升用户体验。
5 增加加载失败的重试机制
为什么需要重试机制?
网络请求可能会失败(如网络不稳定),需要支持自动重试以改善用户体验。
实现方案
- 捕获加载失败的错误。
- 在失败后尝试重新加载数据。
代码示例
let retryCount = 0;
const maxRetry = 3;
async function loadMoreContent() {
try {
const response = await fetch('https://api.example.com/more-content');
if (!response.ok) throw new Error('请求失败');
const data = await response.json();
const container = document.getElementById('content');
data.items.forEach((item) => {
const newItem = document.createElement('div');
newItem.textContent = item.title;
container.appendChild(newItem);
});
retryCount = 0; // 成功后重置重试次数
} catch (error) {
console.error('加载失败:', error);
if (retryCount < maxRetry) {
retryCount++;
console.log(`重试第 ${retryCount} 次`);
loadMoreContent(); // 重试加载
} else {
console.error('多次重试后仍失败');
}
}
}
适用场景
- 网络状况不稳定的场景。
- 后端接口偶尔失败时。
总结
动态加载内容使用户体验更加流畅和优化:
功能点 | 实现方式 | 适用场景 |
---|---|---|
使用 Intersection Observer | 替代滚动事件,性能更高 | 页面滚动监听有性能瓶颈时 |
懒加载图片 | 仅加载视口中的图片 | 内容较多时减少初始加载时间 |
限制最大加载次数 | 手动控制加载上限 | 防止无限滚动影响用户体验或系统性能 |
返回顶部按钮 | 提供快速回到顶部的功能 | 页面内容较长时 |
加载失败重试 | 捕获错误并提供自动重试 | 网络不稳定或接口失败时 |
参考文档:
标签:视口,document,const,Observer,重试,API,newItem,Intersection,加载 From: https://blog.csdn.net/lixin5456985/article/details/144132338