自定义图片懒加载指令的实现
思路
判断图片是否进入到视口区域
如何得知是否进入视口
- 判断距离
- 监听DOM : VueUse
只有进入视口区域才发送网络请求
如何发送默认的网络请求
img.src = url
为图片的 src 属性赋值,浏览器就会自动发送网络请求
实现步骤
- 先创建指令,让指令运行起来
- 在指令的内部实现懒加载的逻辑
实现过程
1、创建自定义指令
// 导入 createApp 方法
import { createApp } from 'vue'
// 导入 App 根组件
import App from './App.vue'
// 调用 createApp 方法 创建 app 实例
const app = createApp(App)
// 注册自定义指令
app.directive('img-lazy', {
/**
* 自定义图片懒加载指令的mounted生命周期
* @description 指令挂载之后自动执行
* @param {HTMLImageElement} el 指令挂载的DOM实例
* @param {Object} binding 该对象的value属性为,指令使用的值,可以通过其获得要进行懒加载处理的图片的url
*/
mounted(el, binding) {
console.log(el, binding.value) // 打印结果为img实例对象,传入的url值
// 图片懒加载的核心逻辑
// ......
}
})
// 挂载 app 实例
app.mount('#app')
2、自定义指令的绑定
<script setup>
// 测试图片的地址
const url = 'https://gw.alipayobjects.com/zos/bmw-prod/0f93c777-5320-446b-9bb7-4d4b499f346d.svg'
</script>
<template>
<!-- 增加占位盒子,将目标图片撑出视口范围 -->
<div class="container">图片懒加载指令的测试</div>
<!-- 绑定指令,传入的值为图片的地址 -->
<img v-img-lazy="url">
</template>
<style lang="scss" scoped>
.container {
height: 1000px;
background-color: wheat;
}
</style>
3、核心逻辑实现
通过 VueUse 工具库中的 hook -- useIntersectionObserver 实现
安装VueUse工具库
npm i @vueuse/core
3.1 如何知道图片进入视口区域
mounted(el, binding) {
// 图片懒加载的核心逻辑
// 1、如何知道图片进入视口区域 通过 VueUse 工具库中的 hook -- useIntersectionObserver 实现
/**
* 通过 useIntersectionObserver 实现对目标对象 el 是否在视口区域的监听
* @description intersectionObserver 为浏览器提供的API,用于监听目标对象是否进入视口区域
* @param {HTMLImageElement} el 目标对象
* @param {boolean} isIntersecting 是否在视口区域
*/
const { stop } = useIntersectionObserver(
el,
([{ isIntersecting }], observerElement) => {
// 如果目标对象在视口区域
console.log(isIntersecting) // 当目标对象进入视口,打印true
},
)
}
3.2 为进入视口区域的图片添加src属性
mounted(el, binding) {
// 图片懒加载的核心逻辑
// 1、如何知道图片进入视口区域 通过 VueUse 工具库中的 hook -- useIntersectionObserver 实现
/**
* 通过 useIntersectionObserver 实现对目标对象 el 是否在视口区域的监听
* @description intersectionObserver 为浏览器提供的API,用于监听目标对象是否进入视口区域
* @param {HTMLImageElement} el 目标对象
* @param {boolean} isIntersecting 是否在视口区域
*/
const { stop } = useIntersectionObserver(
el,
([{ isIntersecting }], observerElement) => {
// 如果目标对象在视口区域
if (isIntersecting) {
// 为目标的src属性赋值为图片的url
el.src = binding.value
// 停止监听 实现性能优化
stop()
}
},
)
}
学自 B站 柴柴_前端教书匠