Vue中图片懒加载不生效,是写法有问题吗?

轩辕艳青 阅读 3

我在用 Vue 3 做一个图片列表页,想用原生 Intersection Observer 实现懒加载,但滚动时图片根本没触发加载,一直显示 loading 占位图。我查了文档也加了 rootMargin,但还是不行。

下面是我组件里的一段代码,是不是哪里写错了?

<template>
  <img 
    v-for="item in images" 
    :key="item.id"
    :data-src="item.url"
    src="loading.gif"
    class="lazy"
    @load="onImageLoad"
  />
</template>

<script setup>
// 省略部分逻辑,observer 在 onMounted 里初始化
</script>
我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
上官广利
这问题的关键是你漏了 IntersectionObserver 的核心实现部分啊,代码里只看到了模板部分。我来详细说下完整解决方案。

首先,懒加载的原理是通过 IntersectionObserver 监测图片是否进入视口,然后替换 src 属性。你现在的代码有两个主要问题:

1. 缺少实际的观察逻辑
2. 图片加载事件绑定在了占位图上,这完全没用

正确的做法应该是这样:

// 在 setup 里
import { onMounted } from 'vue'

const images = 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) // 加载后取消观察
}
})
}, {
rootMargin: '200px' // 提前200px加载
})

// 观察所有懒加载图片
document.querySelectorAll('.lazy').forEach(img => {
observer.observe(img)
})
})


模板部分可以保持原样,但要确保:
1. 所有懒加载图片都有 lazy
2. 真实图片地址放在 data-src,不要直接放 src
3. 移除那个没用的 @load 事件

另外提醒下,现代浏览器其实已经支持原生懒加载了,加个 loading="lazy" 属性就行:
<img src="real.jpg" loading="lazy">
不过如果你需要兼容旧浏览器或者要更精细控制,用 IntersectionObserver 还是必要的。

对了,记得在组件卸载时清理观察器:
onUnmounted(() => {
observer.disconnect()
})


这代码我上周刚在项目里用过,实测有效。你遇到的应该是没正确初始化观察器的问题。
点赞
2026-03-07 16:01