目录
掌握Intersection Observer API,轻松实现实现图片懒加载、元素滚动动画、无限滚动加载等功能
一、什么是 Intersection Observer API?
二、为什么需要 Intersection Observer?
四、使用 Intersection Observer 的关键点
作者:watermelo37
CSDN万粉博主、华为云云享专家、阿里云专家博主、腾讯云、支付宝合作作者,全平台博客昵称watermelo37。
一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。
---------------------------------------------------------------------
温柔地对待温柔的人,包容的三观就是最大的温柔。
---------------------------------------------------------------------
掌握Intersection Observer API,轻松实现实现图片懒加载、元素滚动动画、无限滚动加载等功能
一、什么是 Intersection Observer API?
Intersection Observer API 是浏览器提供的一个强大接口,用来异步观察一个元素是否进入(或者离开)另一个元素或视口(viewport)的可视范围。
通俗地说就是:"我想知道某个元素什么时候滚动到屏幕上了。"
而且,它不会阻塞主线程,性能非常好。
二、为什么需要 Intersection Observer?
在它出现之前,通常我们需要这么做:
window.addEventListener('scroll', function () {
const rect = element.getBoundingClientRect();
if (rect.top < window.innerHeight && rect.bottom > 0) {
console.log('元素进入可视区了');
}
});
这种方法有什么缺点?
-
频繁触发 scroll 事件,性能差。
-
手动判断元素位置,代码复杂。
-
在复杂页面,滚动卡顿很明显。
Intersection Observer 在浏览器底层优化,异步触发并自动判断是否进入可视区,调用简单优雅,完美解决了这些问题!
三、Intersection Observer 如何使用
1、Intersection Observer 基本用法
先来一份最基础的例子:
// 1. 创建观察器
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log('元素进入视口');
observer.unobserve(entry.target); // 停止观察(可选)
}
});
}, {
root: null, // null 代表视口
threshold: 0.1 // 触发时元素可见10%
});
// 2. 选中目标元素
const target = document.querySelector('.target');
// 3. 开始观察
observer.observe(target);
2、图片懒加载
以前:图片一股脑加载 → 网速慢 + 用户体验差
现在:图片快滚到屏幕再加载,省流量 + 加速首屏!
<template>
<div>
<img
v-for="(img, index) in images"
:key="index"
:data-src="img"
src="placeholder.jpg"
class="lazy-image"
ref="lazyImages"
alt="Lazy Load Image"
/>
</div>
</template>
<style scoped>
.lazy-image {
width: 100%;
height: auto;
display: block;
margin-bottom: 20px;
}
</style>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
const images = [
'/img1.jpg',
'/img2.jpg',
'/img3.jpg',
// 更多图片
];
const lazyImages = ref([]);
let observer;
onMounted(() => {
observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
lazyImages.value.forEach(img => {
observer.observe(img);
});
});
onBeforeUnmount(() => {
if (observer) {
observer.disconnect();
}
});
</script>
3、元素入场动画
滚动到元素时添加 .show 类名,播放动画。
<template>
<div>
<div
v-for="(item, index) in 5"
:key="index"
ref="animatedElements"
class="fade-in"
>
内容 {{ index + 1 }}
</div>
</div>
</template>
<style scoped>
.fade-in {
opacity: 0;
transform: translateY(30px);
transition: all 0.6s ease;
}
.fade-in.show {
opacity: 1;
transform: translateY(0);
}
</style>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
const animatedElements = ref([]);
let observer;
onMounted(() => {
observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('show');
observer.unobserve(entry.target);
}
});
}, {
threshold: 0.2
});
animatedElements.value.forEach(el => {
observer.observe(el);
});
});
onBeforeUnmount(() => {
if (observer) {
observer.disconnect();
}
});
</script>
4、无限滚动(加载更多)
滚到底部时自动加载新数据即可,这里只给一个简单的demo,实际实现还需要考虑内存泄漏、用户操作友好性等问题。
<template>
<div>
<div v-for="(item, index) in list" :key="index" class="list-item">
{{ item }}
</div>
<div ref="loadMoreTrigger" class="load-more">
加载更多...
</div>
</div>
</template>
<style scoped>
.list-item {
padding: 10px;
border-bottom: 1px solid #ccc;
}
.load-more {
padding: 20px;
text-align: center;
color: gray;
}
</style>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
const list = ref(Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`));
const loadMoreTrigger = ref(null);
let observer;
const loadMore = () => {
const nextItems = Array.from({ length: 10 }, (_, i) => `Item ${list.value.length + i + 1}`);
list.value.push(...nextItems);
};
onMounted(() => {
observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
loadMore();
}
}, {
threshold: 1.0
});
observer.observe(loadMoreTrigger.value);
});
onBeforeUnmount(() => {
if (observer) {
observer.disconnect();
}
});
</script>
四、使用 Intersection Observer 的关键点
总结下来就是四个关键步骤:
步骤 | 说明 |
---|---|
1 | 用 ref 获取 DOM 元素 |
2 | 在 onMounted 中创建 IntersectionObserver |
3 | 给需要观察的元素 .observe() |
4 | 在 onBeforeUnmount 中 .disconnect() 清理 |
五、结语
Intersection Observer API 是现代 Web 开发不可缺少的利器,掌握它,你可以轻松实现图片懒加载、元素滚动动画、无限滚动加载、页面性能优化等目的。相比传统的 scroll 事件监听能实现全面碾压。
只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
其他热门文章,请关注:
极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图
你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解
通过array.filter()实现数组的数据筛选、数据清洗和链式调用
通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能
TreeSize:免费的磁盘清理与管理神器,解决C盘爆满的燃眉之急
通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制
深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解
el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、DOM操作等
前端实战:基于Vue3与免费满血版DeepSeek实现无限滚动+懒加载+瀑布流模块及优化策略
高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图