我们为什么要实现图片懒加载
图片懒加载是前端页面优化的一种方式,在页面中有很多图片的时候,图片加载就需要很多时间,很耗费服务器性能,不仅影响渲染速度还会浪费带宽,为了解决这个问题,提高用户体验,所以就出现了懒加载这种方式来减轻服务器的压力,优先加载可视区域的内容,其他部分等进入了可视区域再加载,从而提高性能。
实现思路
在图片没有进入可视区域时,先不给的src赋值,这样浏览器就不会发送请求了,等到图片进入可视区域再给src赋值。图片的真实地址需要存储在data-src中。
如何判断元素是可见?
之前:scrollTop ,offsetTop, height .... 计算======>
现在:浏览器有一个API,intersectionObserver 可以用监听元素是否可见
开发中,有vueuse中的useIntersectionObserver这个api。
实现方法
我一般会选择封装成全局指令 <img v-lazy="xxxx" ,配合app.use做成独立的插件。
代码操作
1.封装组件
// 图片懒加载指令注册
import { useIntersectionObserver } from "@vueuse/core";
import defaultIng from '@/assets/images/200.png'
import { App } from "vue";
export default {
install(app: App) {
app.directive('lazy', {
// mounted 是v3 中自定义的指令
mounted(el: HTMLImageElement, { value }) {
// 设置默认图
el.src = defaultIng
const { stop } = useIntersectionObserver(el, ([{isIntersecting}]) => {
if(isIntersecting) {
el.src = value
stop()
}
})
// el是 img 标签
// el.onerror 0级dom事件
// el.onclick=()=>
// el.addEventListener('click')
// el.onerror=()=>{ }
// 加载失败默认图
// el.addEventListener('error',()=>{
// el.src = defaultIng
// })
}
})
}
}
2.在 main.ts 里面注册全局
1 .引入组件
import LazyImg from '@/directive'
2.挂载
app.use(LazyImg)
3.在组件中使用
1. 引入组件
import { useLazyData } from '@/utils/hooks';
2. 在组件里调用请求数据的函数
const target = useLazyData(()=>{
//调用函数
home.getHotList()
})
4.修改src
1. 将 渲染的 :src 改为 v-lazy
:src="item.picture"
改为
v-lazy="item.picture"