开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 13 天、第 13 篇,点击查看活动详情
前言
开发自己项目时想用上图片懒加载,但是百度了一下vue2的v-lazy在vue3已经被弃用了,因此便搜索vue3有没有类似的api但是并没有发现,因此从网上了解到了IntersectionObserver这样一个浏览器api,并用他实现了图片懒加载
图片懒加载的原理已经是老生常谈了,等到图片组件出现在视口内再加载图片,是一种很常见的优化手段,对于图片是否出现在视口的监听,我们仍然可以使用监听scroll或者使用setInterval来判断实现,但是监听scroll会有触发过于频繁而产生性能问题,监听setInterval因为是给其设定一个间歇执行的函数,与理想效果也会有出入,而IntersectionObserver提供了一种异步观察目标元素与其祖先元素或顶级文档视窗(viewport)交叉状态的方法(这是官方的说法),也就是可以实现监听元素在其祖先元素(默认顶级文档视窗)的可视状态
我们利用Vue3的自定义指令,我这里自定义了一个v-lazyload指令,在需要懒加载的img标签上使用,在页面刚渲染时为它绑定IntersectionObserver监听器,直到目标元素是否出现在了视口才将图片链接绑定在标签的src属性上,如果图片加载失败显示默认图片。
实现
IntersectionObservera接受两个参数
第一个参数是一个函数,也就是监听的回调,传入的参数是一个对象数组,包含祖先元素与目标元素的信息以及一些参数,第二个参数是配置属性,可选,详情可参考IntersectionObserver
以下为实现代码
import defaultImg from '@/assets/img/products/product_placeholder_square_medium.jpg'
//图片加载失败是现实的图片
const defineDirective = (app) => {
// 扩展自定义指令
app.directive('lazyload', {
// Vue3种自定义指令关联到了生命周期,这里使用mounted
mounted(el, bindings) {
// el表示使用指令的DOM元素
// bindings表示指令传入的内容,是一个对象
// 1、用IntersectionObserver监听图片进入可视区
const oberver = new IntersectionObserver((cahnges) => {
// console.log(cahnges)
if (cahnges[0].isIntersecting) {
// console.log(isIntersecting, bindings.value)
// 进入了可视区
// 2、给图片的src属性赋值图片的地址
el.src = bindings.value
// 取消图片的监听
oberver.unobserve(el)
// 加载的图片失败了,显示默认的图片地址
el.onerror = () => {
// 显示默认图片
el.src = defaultImg
}
}
})//不配置第二个参数,使用API的默认配置
oberver.observe(el)//挂载监听器
}
})
}
export default {
install(app) {// 自定义指令指令导出
defineDirective(app)
}
}
将这部分代码封装成自己的api以后,在全局注册
import { createApp } from 'vue'
import App from './App.vue'
import imgLazy from '@/utils/imgLazy.js'
const app = createApp(App)
app.use(imgLazy)
app.mount('#app')
之后在组件中使用就跟vue2中没差别,直接在需要懒加载的标签使用v-lazyload指令就可以。
<figure class="imgBox">
<img v-lazyload="props.imgA" class="imgA" />
<img v-if="props.imgB" v-lazyload="props.imgB" class="imgB"/>
</figure>
记得v-lazyload要绑定自己的图片的链接,是不是非常的简单又实用
最后再打个广告,关注公众号程序猿青空,不定期分享各种优秀文章、学习资源、学习课程,能在未来(因为现在还没啥东西)享受更多福利。