npm i vue-lazyload -S
import VueLazyload from "vue-lazyload";
Vue.use(VueLazyload)
Vue.use(VueLazyload,{
// 设置相应的 loading 图和图片错误显示图
error: require('@/assets/lazy/error.png'),
loading: require('@/assets/lazy/loading.gif'),
attempt: 1, // 尝试加载图片数量
// try: 2 // 加载图片数量
})
单图
<img v-lazy ='图片地址' :key='图片地址'>
多图
<div v-lazy-container="{ selector: 'img' }">
<img data-src="图片地址">
<img data-src="图片地址">
<img data-src="图片地址">
<img data-src="图片地址">
</div>
v-lazy:background-image = ''
要注意图片和盒子大小问题属性 | 作用 | 默认值 | 类型 |
---|---|---|---|
preLoad |
预加载高度比例 | 1.3 |
Number |
error |
图片路径错误时加载图片 | 'data-src' |
String |
loading |
预加载图片(占位图片) | 'data-src' |
String |
attempt |
尝试加载图片数量 | 3 |
Number |
先储存图片地址 不能先放在src上(放在src上直接发请求了) 当图片进入可视区 将src地址换成存储地址
isIntersecting
用来判断进入或离开app.directive() 传入自定义指令的名称和配置
当使用指令的DOM创建好后,创建一个观察对象 来观察当前使用指令的元素并开始观察
当进入可视区后停止观察
把指令的值设置给 el 的 src 属性 ( binding.value 就是指令的值 )
处理图片加载失败 error是图片加载失败的事件 加载失败后设置默认图 load是图片加载成功
// 图片地址(可通过
import defaultImg from '@/assets/images/200.png'
// 定义指令
const defineDirective = (Vue) => {
// 1.图片懒加载 v-lazy 指令directive
Vue.directive('lazy', {
// 监听使用指令的DOM是否创建好
// el -->传入的dom binding --->传入的图片路径
inserted(el,binding) {
// 2.创建一个观察对象 来观察当前使用指令的元素
const observe = new IntersectionObserver(([{isIntersecting}]) => {
if (isIntersecting) {
// 进入可视区
// 停止观察
observe.unobserve(el)
// 3.把指令的值设置给el的src属性 binding.value 就是指令的值
// 4.处理图片加载失败 error是图片加载失败的事件 load是图片加载成功
el.onerror = () => {
// 加载失败 设置默认图
el.src = defaultImg
}
el.src = binding.value
}
}, {
threshold:0.01
})
// 开启观察
observe.observe(el)
},
})
}
export default{
install(Vue){
defineDirective(Vue)
}
}
import defaultImg from '@/assets/images/200.png'
// 定义指令
const defineDirective = (app) => {
// 1.图片懒加载 v-lazy 指令directive
// 原理:先储存图片地址 不能先放在src上(放在src上直接发请求了) 当图片进入可视区 将src地址换成存储地址
app.directive('lazy', {
// 监听使用指令的DOM是否创建好
// el -->传入的dom binding --->传入的图片路径
mounted(el,binding) {
// 2.创建一个观察对象 来观察当前使用指令的元素
const observe = new IntersectionObserver(([{isIntersecting}]) => {
if (isIntersecting) {
// 进入可视区
// 停止观察
observe.unobserve(el)
// 3.把指令的值设置给el的src属性 binding.value 就是指令的值
// 4.处理图片加载失败 error是图片加载失败的事件 load是图片加载成功
el.onerror = () => {
// 加载失败 设置默认图
el.src = defaultImg
}
el.src = binding.value
}
}, {
threshold:0.01
})
// 开启观察
observe.observe(el)
},
})
}
export default {
install (app) {
defineDirective(app)
}
}
当模块进入到 可视区 ,再发请求获取数据
任务目标:
了解如何检测目标元素的可见性
技术方案:
我们可以使用 @vueuse/core
中的 useIntersectionObserver
来实现监听组件进入可视区域行为,需要配合 vue3
的组合 API
的方式才能实现
先分析下这个useIntersectionObserver 函数:
核心单词解释:
<script setup lang="ts">
import { ref } from 'vue';
import { useIntersectionObserver } from '@vueuse/core';
// 准备目标元素(DOM节点或组件,需配合模板 ref 使用)
const target = ref(null);
const { stop } = useIntersectionObserver(target, ([{ isIntersecting }]) => {
console.log('检测元素可见性', isIntersecting);
// 需求:如果目标元素进入可视区,就发送请求,并停止检测
if (isIntersecting) {
// 当目标元素进入可视区域时,才发送请求
console.log('进入可视区,需要发送请求');
// 请求已发送,主动停止检查
stop();
}
});
</script>
<template>
<div style="height: 2000px"></div>
<!-- 目标元素需添加模板 ref -->
<div ref="target">
<h1>我是目标元素</h1>
</div>
<div style="height: 2000px"></div>
</template>
我们以新鲜好物模块为例演示一下这个函数的使用方式
1)通过 ref
属性获得组件实例并测试
2)使用useIntersectionObserver
监听函数
<script setup lang="ts">
import HomePanel from "./home-panel.vue";
import { ref } from "vue";
import { useIntersectionObserver } from "@vueuse/core";
import useStore from "@/store";
const { home } = useStore();
// 通过 ref 获得组件实例
const target = ref(null);
const { stop } = useIntersectionObserver(
// target 被检测的目标元素
target,
// isIntersecting 是否进入可视区域
([{ isIntersecting }]) => {
// 在此处可根据isIntersecting来判断,然后做业务
console.log('是否进入可视区域', isIntersecting);
if (isIntersecting) {
home.getHotGoodsList();
stop();
}
}
);
script>
<template>
<div class="home-hot">
<HomePanel ref="target" title="人气推荐" sub-title="人气爆款 不容错过">
...
HomePanel>
div>
template>
3)测试效果
打开浏览器,人气推荐模块还未进入到可视区,打印值为false,
然后我们滑动页面,当人气模块
组件进入可视区中时,再次发生打印,此时为true,
到此我们就可以判断组件进入和离开可视区了
❗特别注意:每次被监听的dom进入离开可视区时都会触发一次,而不是只触发一次, 可以stop关闭监听