vue实现懒加载图片
使用 Intersection Observer API
Intersection Observer API 是现代浏览器提供的原生 API,用于检测目标元素是否进入视口。在 Vue 中可以通过自定义指令或组件实现懒加载。
// 自定义指令实现
Vue.directive('lazy', {
inserted: (el, binding) => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
el.src = binding.value
observer.unobserve(el)
}
})
})
observer.observe(el)
}
})
<!-- 使用方式 -->
<img v-lazy="imageUrl" alt="lazy image">
使用 vue-lazyload 插件
vue-lazyload 是社区成熟的懒加载解决方案,支持占位图、加载失败处理等高级功能。
安装插件:
npm install vue-lazyload
配置使用:

import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload, {
preLoad: 1.3,
error: 'error.png',
loading: 'loading.gif',
attempt: 3
})
模板中使用:
<img v-lazy="imageUrl">
实现图片加载状态反馈
可以扩展自定义指令实现加载中和加载失败的视觉反馈:

Vue.directive('lazy', {
bind: (el, binding) => {
el.dataset.src = binding.value
el.src = 'placeholder.png'
},
inserted: (el) => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = new Image()
img.src = el.dataset.src
img.onload = () => {
el.src = img.src
el.classList.add('loaded')
}
img.onerror = () => {
el.src = 'error.png'
el.classList.add('error')
}
observer.unobserve(el)
}
})
})
observer.observe(el)
}
})
响应式图片处理
结合 picture 元素和 srcset 实现响应式懒加载:
<picture>
<source
v-lazy="imageWebp"
type="image/webp"
media="(min-width: 1200px)">
<source
v-lazy="imageJpeg"
type="image/jpeg"
media="(min-width: 1200px)">
<img
v-lazy="fallbackImage"
alt="responsive lazy image">
</picture>
性能优化建议
设置适当的 rootMargin 可以提前触发加载:
const observer = new IntersectionObserver(callback, {
rootMargin: '200px 0px'
})
对于大量图片列表,考虑使用虚拟滚动技术结合懒加载。在 Vue 3 中可以使用 Composition API 封装可复用的懒加载逻辑。
// Vue 3 Composition API
export function useLazyLoad(options) {
const observedEl = ref(null)
onMounted(() => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// 加载逻辑
observer.unobserve(entry.target)
}
})
}, options)
if (observedEl.value) {
observer.observe(observedEl.value)
}
onUnmounted(() => observer.disconnect())
})
return { observedEl }
}






