Vue-lazyload 是一个基于 Vue.js 的图片懒加载库,它的实现原理是基于 Intersection Observer API。Intersection Observer API 是一种异步观察目标元素与其祖先元素或顶级文档视窗交叉状态的方式。
Vue-lazyload 的实现原理如下:
- 在需要懒加载的图片元素上添加一个自定义指令 v-lazy,并将其参数传递给 Vue-lazyload 组件。
- Vue-lazyload 组件通过 Intersection Observer API 监听目标元素的交叉状态,即当目标元素进入可视区域时触发回调函数。
- 在回调函数中,Vue-lazyload 组件会通过 $emit 触发一个加载事件,通知父组件加载图片。
- 父组件在接收到加载事件后,会通过 $src 或者其他方式设置图片的真实路径,完成图片的加载。
通过这种方式,Vue-lazyload 可以实现图片的懒加载,即在图片进入可视区域时才加载,从而提高页面加载速度和性能。
一、使用Vue本身的指令
Vue本身提供了一个指令v-lazy,可以实现图片懒加载。使用方式如下:
<img v-lazy="imageSrc" />
其中,imageSrc是需要懒加载的图片路径。当图片进入可视区域时,Vue会自动加载图片。
二、使用第三方库(推荐)
vue社区中有许多第三方库可以实现图片懒加载,例如vue-lazyload、vue-lazyload-enhanced等。这些库提供了更多的配置项和功能,可以满足更多的需求。使用方式如下:
2.1 安装下载
npm i [email protected] -S
2.2 main.js 导入
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyLoad, {
// 可选配置项,可省略
error: require('./error.jpg'), // 加载失败时显示的图片
loading: require('./loading.gif'), // 加载中时显示的图片
preLoad: 1.3, // 预加载高度的比例
attempt: 3 // 尝试加载次数
})
2.3 页面使用
<template>
<div>
<img v-lazy="imageSrc" />
</div>
</template>
<script>
import Vue from 'vue' // main.js 已引入的可忽略
import VueLazyload from 'vue-lazyload' // main.js 已引入的可忽略
Vue.use(VueLazyload, { // main.js 已引入的可忽略
// 配置项...
})
</script>
// 个人实操使用,可参考
<template>
<div class="scroll-container">
<div class="demo-image__lazy">
<img v-for="(url, index) in imgUrl" :key="index" v-lazy="url" /> // 遍历图片
</div>
</div>
</template>
<script>
export default {
data() {
return {
imgUrl: [ // 需要显示的所有图片
require('@/assets/help/1.jpg'),
require('@/assets/help/2.jpg'),
require('@/assets/help/3.jpg'),
require('@/assets/help/4.jpg'),
require('@/assets/help/5.jpg'),
],
}
},
}
</script>
<style lang="less" scoped> // 根据视口大小显示图片宽度
@media screen and (max-width: 1200px) {
.demo-image__lazy img {
width: 100%;
}
}
@media screen and (min-width: 1200px) {
.demo-image__lazy img {
width: 50%;
}
}
</style>
三、自定义指令
除了使用Vue本身的指令和第三方库外,还可以通过自定义指令来实现图片懒加载。在自定义指令中,可以通过Intersection Observer API来监听目标元素的交叉状态,从而实现图片的懒加载。使用方式如下:
<template>
<div>
<img v-lazyload="imageSrc" />
</div>
</template>
<script>
export default {
directives: {
lazyload: {
inserted: function (el, binding) {
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
const img = new Image()
img.src = binding.value
el.appendChild(img)
observer.unobserve(el)
}
}, {threshold: 0.1})
observer.observe(el)
}
}
}
}
</script>