Vue项目性能优化之—自定义指令实现图片懒加载、首屏渲染优化(组件数据懒加载)、vue-lazyload的使用
1 安装 vue-lazyload
2 在 main.js 中进行引用
3 自定义配置插件
-
Vue.use(VueLazyload,{
error: require('@/assets/lazy/error.png'),
loading: require('@/assets/lazy/loading.gif'),
attempt: 1,
})
4 使用
- ??注:
- 背景图片中使用懒加载
v-lazy:background-image = '' 要注意图片和盒子大小问题 - 使用时可以添加一个 key 属性
补充
属性 | 作用 | 默认值 | 类型 |
---|
preLoad | 预加载高度比例 | 1.3 | Number | error | 图片路径错误时加载图片 | 'data-src' | String | loading | 预加载图片(占位图片) | 'data-src' | String | attempt | 尝试加载图片数量 | 3 | Number |
自定义指令实现图片懒加载
实现原理:
先储存图片地址 不能先放在src上(放在src上直接发请求了) 当图片进入可视区 将src地址换成存储地址
-
callback
-
两个回调参数 entries , observer
- entries
- 被观察的元素信息对象的数组 [{元素信息},{}],信息中的
isIntersecting 用来判断进入或离开 - observer
-
options 配置参数
-
root
-
rootMargin
-
threshold
-
实例提供的两个方法
-
observe(dom)
-
unobserve(dom)
实现步骤
-
app.directive() 传入自定义指令的名称和配置 -
当使用指令的DOM创建好后,创建一个观察对象 来观察当前使用指令的元素并开始观察 -
当进入可视区后停止观察 -
把指令的值设置给 el 的 src 属性 ( binding.value 就是指令的值 ) -
处理图片加载失败 error是图片加载失败的事件 加载失败后设置默认图 load是图片加载成功
代码实现
import defaultImg from '@/assets/images/200.png'
const defineDirective = (Vue) => {
Vue.directive('lazy', {
inserted(el,binding) {
const observe = new IntersectionObserver(([{isIntersecting}]) => {
if (isIntersecting) {
observe.unobserve(el)
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) => {
app.directive('lazy', {
mounted(el,binding) {
const observe = new IntersectionObserver(([{isIntersecting}]) => {
if (isIntersecting) {
observe.unobserve(el)
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 函数:
🔔核心单词解释:
- useIntersectionObserver 检查元素是否进入可视区函数
- target 目标元素,🎯需配合模板 ref 使用
- isIntersecting 是否进入可视区(布尔值)
- stop 用于停止检测的函数
<script setup lang="ts">
import { ref } from 'vue';
import { useIntersectionObserver } from '@vueuse/core';
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();
const target = ref(null);
const { stop } = useIntersectionObserver(
target,
([{ 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关闭监听
|