Vue3中实现lazy-img,懒加载图片指令
1. 安装依赖
npm install @vueuse/core
2. 创建懒加载指令
创建 src/directives/imgLazy.js 文件:
import { useIntersectionObserver } from '@vueuse/core'
export const imgLazyDirective = {
mounted(el, binding) {
// 设置默认占位图
el.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIwMCIgaGVpZ2h0PSI1MDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3QgZmlsbD0iI2Y1ZjVmNSIgd2lkdGg9IjEyMDAiIGhlaWdodD0iNTAwIi8+PHRleHQgZmlsbD0iIzc1NzU3NSIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjQwIiBkeT0iMTMuNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNjAwIiB5PSIyNTAiPkxvYWRpbmcuLi48L3RleHQ+PC9zdmc+' // 占位图
const { stop } = useIntersectionObserver(
el,
([{ isIntersecting }]) => {
if (isIntersecting) {
// 元素进入视口,加载真实图片
el.src = binding.value
stop() // 停止观察
}
}
)
}
}
3. 注册全局指令
在 src/main.js 中注册:
import { createApp } from 'vue'
import { imgLazyDirective } from './directives/imgLazy'
const app = createApp(App)
app.directive('img-lazy', imgLazyDirective)
4. 在组件中使用
<script setup>
import { getBannerAPI } from '@/apis/home'
import { onMounted, ref } from 'vue'
const bannerList = ref([])
const getBanner = async () => {
const res = await getBannerAPI()
bannerList.value = res.result
}
onMounted(() => {
getBanner()
})
</script>
<template>
<div class="home-banner">
<el-carousel height="500px">
<el-carousel-item v-for="item in bannerList" :key="item.id">
<img v-img-lazy="item.imgUrl" :alt="item.alt || 'banner image'">
</el-carousel-item>
</el-carousel>
</div>
</template>
<style scoped lang='scss'>
.home-banner {
width: 1240px;
height: 500px;
position: absolute;
left: 0;
top: 0;
z-index: 98;
img {
width: 100%;
height: 500px;
}
}
</style>
5.关键优势
性能优化:只有当图片即将进入视口时才加载
用户体验:减少初始加载时间
资源节省:避免不必要的网络请求
简单易用:通过指令方式轻松集成
6.使用vue3插件进行优化
main.js直接use

// 定义懒加载插件
import { useIntersectionObserver } from '@vueuse/core'
export const lazyPlugin = {
install (app) {
// 懒加载指令逻辑
app.directive('img-lazy', {
mounted (el, binding) {
// el: 指令绑定的那个元素 img
// binding: binding.value 指令等于号后面绑定的表达式的值 图片url
// console.log(el, binding.value)
el.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIwMCIgaGVpZ2h0PSI1MDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3QgZmlsbD0iI2Y1ZjVmNSIgd2lkdGg9IjEyMDAiIGhlaWdodD0iNTAwIi8+PHRleHQgZmlsbD0iIzc1NzU3NSIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjQwIiBkeT0iMTMuNiIgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iNjAwIiB5PSIyNTAiPkxvYWRpbmcuLi48L3RleHQ+PC9zdmc+' // 占位图
const { stop } = useIntersectionObserver( // 检查元素是否进入视口区域
el,
([{ isIntersecting }]) => {
// console.log(isIntersecting)
if (isIntersecting) {
// 进入视口区域
el.src = binding.value
stop()
}
},
)
}
})
}
}
本文来自博客园,作者:一个小笨蛋,转载请注明原文链接:https://www.cnblogs.com/paylove/p/19233096

浙公网安备 33010602011771号