前言: 在开发中如果遇到加载慢的问题,经常需要对项目进行优化. 常见的优化方案有资源加载优化和页面渲染优化. 这篇文章终点记录下图片懒加载 和 数据懒加载 方面的优化原理及实现方案
图片懒加载原理
1. 开始时, 不设置src属性
2. 当图片**可见**时, 设置src, 去加载图片
如何判断元素是可见?
之前: scrollTop, offsetTop, height...计算
现在: 浏览器有一个API, intersectionObserver 可以监听元素是否可见,
开发中: 有vueuse中的useIntersectionObserver这个api.
实现代码
这里是在一个单独的文件中自定义了一个全局的指令v-lazy,
后面要使用就直接在main.ts中引入这个文件
然后app.use(XXX) 注册成全局插件;
在要用的图片上不设置src属性;设置v-lazy="图片地址"
import { useIntersectionObserver } from '@vueuse/core'
import { App } from 'vue'
import defaultImg from '@/assets/images/200.png'
export default {
install(app: App) {
// 全局指令
app.directive('lazy', {
// mounted是v3中自定义指令的生命周期, 它会自动被调用
// 它表示的含义和组件mounted是一致的
// el是dom元素, binding
mounted(el, binding) {
// 设置默认图片
el.src = defaultImg
console.log('lazy', el, binding.value)
// 实时监听el是否可见, 如果可见, 给它设置binding.value
const { stop } = useIntersectionObserver(el, ([{isIntersecting}]) => {
if (isIntersecting) {
el.src = binding.value
// 停止
stop()
el.onerror = () => {
el.src = defaultImg
}
}
})
}
})
}
}
数据懒加载
场景: 主页上有喝多模块, 每个模块都发ajax拿数据,并且是在组件创建时发的请求. 这样就有一个后果, 靠近底层的模块其实用户都看不到,这个请求发送就有点浪费了
思路: 判断当前模块是否可见, 可见就发请求
做法: 封装一个自定义的hooks,接收一个回调, 返回ref.这个ref可以用在模块外层的dom上: 当这个ref引用的dom可见时,就执行回调(发请求)
实操: 借用vueuse, useIntersectionObserver去封装.
代码实现, 单独封装一个方法, 然后在要用的地方直接引入这个方法, 传一个回调函数
import { useIntersectionObserver } from '@vueuse/core';
import { onMounted, ref } from 'vue';
// 接收一个回调, 返回一个ref引用
// 功能: 当ref引用的dom处于可见状态是, 调用一次回调函数
export function useLazyData( fn: () => void ) {
const target = ref(null)
// 当整个组件处于可见状态时才发ajax
onMounted(() => {
const { stop } = useIntersectionObserver(target.value, ([{ isIntersecting }]) => {
// 可见
if (isIntersecting) {
// 发请求
fn()
// 停止监听
stop()
}
})
})
return target
}