直接上代码
/**
* @Author : xlsir
* @Description: 图片懒加载指令
* @Create_time: 2025-08-03 10:34
*/
const ob = new IntersectionObserver(entries => {
for (const entry of entries) {
if (entry.isIntersecting) {
const img = entry.target;
// 图片预加载
preloadImage(img)
ob.unobserve(img);
}
}
}, {
rootMargin: '200px',
threshold: 0.01
});
//预加载
const preloadImage = (imgElement) => {
const src = imgElement.dataset.src;
if (!src) return;
// 创建预加载的Image对象
const preloadImg = new Image();
preloadImg.src = src;
// 预加载完成后再赋值给实际img元素
preloadImg.onload = () => {
imgElement.src = src;
imgElement.removeAttribute('data-src');
};
// 加载失败时设置错误处理
preloadImg.onerror = () => {
imgElement.src = ''; // 或设置默认错误图片
imgElement.removeAttribute('data-src');
};
}
// 判断元素有没有在视口
function isBelowViewport(el) {
const rect = el.getBoundingClientRect()
return rect.top - window.innerWidth > 0
}
export default {
mounted(el) {
//当元素处于视口 直接记载 而不是 观测
if (!isBelowViewport(el)) {
preloadImage(el);
return
}
ob.observe(el);
},
unmounted(el) {
ob.unobserve(el);
}
};
如何使用
main.js注册
import { createApp } from 'vue' import App from './App.vue' import vLazyImg from '@/directives/vLazyImg.js' //引入指令文件 const app = createApp(App) app.directive('img-lazy',vLazyImg) app.mount('#app')
文件使用
<img v-lazy-img>