概念:
懒加载是指在页面加载完成后,只加载用户当前可见区域或即将进入可见区域的内容。
通过延迟加载非必要资源,可以减少初始页面加载时间和网络请求量,提升页面的性能和用户体验。常见的应用场景包括图片懒加载、按需加载组件、延迟加载无限滚动列表等。
预加载是指在页面展示之前提前加载即将使用到的资源,以提高用户访问页面时的加载速度。
通过在HTML头部添加<link rel="preload">或JavaScript进行动态加载,可以预先获取需要的资源(如CSS、JavaScript、字体文件等),从而加速后续的页面渲染。预加载常用于提高首屏渲染速度、提前下载核心资源和优化用户体验。
懒加载与预加载的区别:
1.懒加载和预加载都是为了提升页面性能和用户体验而采取的优化手段。两者可以结合使用,根据具体场景和需求进行选择。
2.懒加载主要关注延迟加载非必要内容,减少请求数量和加载时间;而预加载则更侧重于提前加载可能需要的资源,加快页面加载速度。
方法:
一、懒加载:
1.使用Intersection Observer API:Intersection Observer API 是浏览器提供的一种用于异步监听目标元素与其父级或视窗交叉状态的API。我们可以使用 Intersection Observer API 监听元素是否进入了视窗可见区域,如果进入了可见区域,再进行相应的加载操作。
// 创建IntersectionObserver实例(这个实例对象上有一个observe方法)
const observer = new IntersectionObserver((entries, observer) => {
// 上述构造函数接收一个回调函数,函数接收的第一参数是被监听元素组成的数组,
//遍历每个观察到的元素
entries.forEach(entry => {
// 如果元素可见
if (entry.isIntersecting) {
const lazyImage = entry.target;
// 加载图片
lazyImage.src = lazyImage.dataset.src;
lazyImage.classList.remove('lazy-load');
// 停止对该元素的观察
observer.unobserve(lazyImage);
}
});
});
// 获取所有需要懒加载的元素
const lazyLoadElements = document.querySelectorAll('.lazy-load');
// 遍历每个需要懒加载的元素,并开始观察
lazyLoadElements.forEach(element => {
observer.observe(element);
});
在上述代码中,首先创建一个IntersectionObserver
实例,使用其回调函数来处理可见性变化的元素。在回调函数中,遍历每个观察到的元素,并判断是否进入了视口(isIntersecting
属性为true
)。如果元素进入了视口,就加载图片,并移除lazy-load
类。然后,停止对该元素的观察,以提升性能。
接下来,我们通过querySelectorAll
方法获取所有需要懒加载的元素,并遍历它们。
对于每个需要懒加载的元素,调用observer.observe(element)
方法开始观察。
还 可以根据需要修改选择器和添加其他操作,例如加载其他资源或执行动画。
2.自定义JavaScript实现:通过监听滚动事件,判断目标元素是否进入可见区域,如果目标元素已经进入可见区域,就触发加载操作。可以通过获取滚动条位置、计算元素相对于视窗的位置等方式来判断目标元素的可见性。
// 获取所有需要懒加载的元素(此处元素类名为lazy-load)
const lazyLoadElements = document.querySelectorAll('.lazy-load');
// 定义一个滚动事件处理函数
function lazyLoad() {
// 遍历每个需要懒加载的元素
lazyLoadElements.forEach(element => {
// 如果元素已经加载过,则跳过。(查看元素是否有data-loaded属性,有,就跳过)
if (element.getAttribute('data-loaded')) return;
// 获取元素相对于文档顶部的距离
const elementTop = element.offsetTop;
// 判断是否滚动到了元素的位置
if (window.innerHeight + window.scrollY >= elementTop) {
// 加载元素
element.src = element.getAttribute('data-src');
element.setAttribute('data-loaded', true);
}
});
}
// 监听滚动事件
window.addEventListener('scroll', lazyLoad);
// 初始化页面加载
lazyLoad();
3.使用第三方库或插件:许多前端框架和库都提供了懒加载的支持。例如,React 可以使用 React Lazy 和 Suspense 组件实现组件的懒加载;jQuery LazyLoad 插件可以用于图片的懒加载。
预加载
监听视口变化
// 创建IntersectionObserver实例
const observer = new IntersectionObserver((entries, observer) => {
// 遍历每个观察到的元素
entries.forEach(entry => {
// 如果元素进入了视口
if (entry.isIntersecting) {
const preloadImage = entry.target;
// 创建一个新的Image对象
const image = new Image();
// 监听图片加载完成事件
image.onload = () => {
// 将预加载的图片设置为原始图片
preloadImage.src = image.src;
// 停止对该元素的观察
observer.unobserve(preloadImage);
};
// 设置Image对象的src为原始图片路径
image.src = preloadImage.dataset.src;
}
});
}, { threshold: 0.5 }); // 添加阈值以延迟加载
// 获取所有需要预加载的元素
const preloadElements = document.querySelectorAll('.preload');
// 遍历每个需要预加载的元素,并开始观察
preloadElements.forEach(element => {
observer.observe(element);
});
创建了一个IntersectionObserver
实例,并传入回调函数。
在回调函数中,遍历了entries
数组,判断观察到的元素是否进入了视口(isIntersecting
)。
如果元素进入了视口,就创建一个新的Image
对象,并设置其onload
事件监听器。
在图片加载完成后,我们将预加载的元素的src
属性设置为原始图片的路径。
最后,我们使用observer.unobserve()
方法停止对该元素的观察,以提升性能。
你可以根据需求修改选择器、添加阈值、预加载其他资源等。