前言
都2023了,你一个搞前端的5分钟还搞不出图片懒加载???
本文是探讨的是"图片懒加载"
此文章是个人学习归纳的心得, 为掘金首发 , 如有不对, 还望指正, 感谢!
如果你5分钟能搞出来,那就不用看这篇文章了
原理
简单来说原理
图片懒加载的原理就是利用img标签的特性,当img标签的src属性是一个空地址,那么浏览器就不会加载这个图片,当地址为有效值的时候就加载,然后通过img的这个特性,通过js判断一下图片是否进入窗口,就可以动态控制src的值,从而实现图片的懒加载
具体来讲原理
图片懒加载是一种优化网页性能的技术,它的原理是在页面加载时只加载可见区域内的图片,当用户滚动到图片所在的位置时再进行加载。这样可以减少初始页面加载所需的资源和时间,提高页面的加载速度和用户体验。
-
初始状态:在页面加载时,所有的
<img>标签的src属性都设置为一个占位符或者空字符串,而不是实际的图片地址。这样浏览器在渲染页面时不会去下载这些图片。 -
监听滚动事件:通过 JavaScript 监听页面的滚动事件,以便检测用户是否滚动到了指定的位置。
-
判断可见区域:当用户滚动页面时,通过计算可视区域的位置和大小,判断哪些图片进入了可见区域。
-
加载图片:当图片进入可见区域时,将对应的
<img>标签的src属性设置为实际的图片地址。这会触发浏览器下载图片并将其显示在页面上。 -
停止监听:一旦所有的图片都加载完毕,或者用户离开了页面,停止监听滚动事件,以避免额外的性能开销。
通过图片懒加载,页面一开始只加载可见区域内的图片,其它图片在需要时才进行加载,从而减少了初始加载的资源量和时间。这对于包含大量图片的长页面或者需要展示大量图片的相册等场景非常有用。
在Vue3框架自定义指令实现懒加载
前置知识
什么? 造轮子? 我是程序员哎? 造个屁的轮子, 目前图片懒加载的原理已经剖析透了, 要做的无非就是判断图片是否进入窗口,然后进行src的动态替换, 其实也不难,但是已经有轮子了,我们没必要再造轮子了。
在VueUse里面就有很多好用的轮子,就看你去发现,留个印象就行了,方便以后找,咱们这次使用的是useIntersectionObserver函数,
具体链接地址如下: useIntersectionObserver | VueUse
为了以后也可以用,我们就把这个自定义指令,以插件的形式来定义,具体定义规则,可以看vue3官方文档
具体链接: 插件 | Vue.js (vuejs.org)
Vue3中如何定义基本指令的语法规则,你也要知道,不知道的可以看官方文档的介绍,链接如下
具体链接:自定义指令 | Vue.js (vuejs.org)
具体实现
使用VueUse之前,要先安装VueUse,在Vue的项目的终端执行下面的命令
npm i @vueuse/core
新建一个js文件,敲入以下代码,注释我写的很详细了
// 定义懒加载插件
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) 可以自己打印看一下
//useIntersectionObserver函数是VueUse里面的函数,用于判断是否在窗口
const { stop } = useIntersectionObserver(
el,
([{ isIntersecting }]) => {
// console.log(isIntersecting)
if (isIntersecting) {
// 进入视口区域
el.src = binding.value
stop() //手动停止,stop函数是useIntersectionObserver的返回值
}
},
)
}
})
}
}
详细解释:
-
import { useIntersectionObserver } from '@vueuse/core'导入了 VueUse 库中的useIntersectionObserver函数,用于观察元素的可见性。 -
lazyPlugin是一个对象,其中包含一个install方法。该方法在插件安装时会被调用。 -
app.directive('img-lazy', {...})定义了一个名为img-lazy的指令。这个指令可以在 Vue 组件的模板中使用,用于懒加载图片。 -
mounted(el, binding)是指令的钩子函数,在指令绑定的元素(在这里是<img>元素)被插入到 DOM 时被调用。 -
el参数是指令绑定的元素,即<img>元素。 -
binding参数是指令的绑定对象,包含了指令的一些信息,其中binding.value是指令等于号后面绑定的表达式的值,即图片的 URL。 -
useIntersectionObserver函数用于创建一个 Intersection Observer 对象,并传入需要观察的元素el和一个回调函数。回调函数接收一个参数[{ isIntersecting }],其中isIntersecting表示元素当前是否处于视口内。 -
当图片元素进入视口区域时,回调函数中的
if (isIntersecting)条件成立,将绑定的图片 URL 赋值给el.src,从而触发图片加载。 -
调用
stop()函数停止在图片加载后的监视,以避免不必要的性能开销。
然后我们在main.js函数里面调用就可以了
// 全局指令注册
import { directivePlugin } from '@/directives'
app.use(directivePlugin)
现在这就是一个全局指令了,我们可以这样使用
<img v-img-lazy="图片路径" />
其实也就是代替了src属性。