您现在的位置是:首页 >学无止境 >使用v-lazy实现VUE3图片懒加载技术网站首页学无止境
使用v-lazy实现VUE3图片懒加载技术
项目场景:
图片懒加载是常见的性能优化方法,在图片很多或加载图片出现网络延迟的情况下,使用懒加载可以减少网络请求、提高用户体验感。
实现原理:在图片没进入可视区域前,使用默认的图片;在进入可视区域并加载好之后,再替换图片的默认src路径,展示真实图片。
vue3已经封装好了v-lazy自定义指令,直接安装使用即可
使用方法:
1、vue3 安装 vue-lazy
npm install vue3-lazy -S
也可以用yarn安装
2、在main.js里面全局注册
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).use(lazyPlugin, {
loading: require('@/assets/images/default.png'), // 图片加载时默认图片
error: require('@/assets/default.png') // 图片加载失败时默认图片
// 还可以有其他配置
})
3、template中使用
<div id="app">
<img v-lazy="../xxx.png">
</div>
原作者github地址(源码):https://github.com/ustbhuangyi/vue3-lazy
实现原理
Vue.js虽然是数据驱动+组件化,但还是避免不了手动操作DOM的情况,于是设计了自定义指令,允许用户做一些底层的DOM操作。v-lazy就是使用自定义指令实现的。
自定义指令官网:https://cn.vuejs.org/guide/reusability/custom-directives.html#directive-hooks
为了自定义指令方便的给多个项目使用,可以把它做成插件:
const lazyPlugin = {
install (app, options) {
app.directive('lazy', {
// 指令对象
})
}
}
export default lazyPlugin
然后在项目中使用:
import { createApp } from 'vue'
import App from './App.vue'
import lazyPlugin from 'vue3-lazy'
createApp(App).use(lazyPlugin, {
// 添加一些配置参数
})
通常vue3的插件会暴露install函数,当app实例use该插件时,就会执行函数。在install函数内部,通过app.directive去注册一个全局指令,这样就可以在组件中使用了。
v-lazy的实现原理:https://zhuanlan.zhihu.com/p/439390274
判断图片是否进入可视区域
判断图片是否进入可视区域使用的是 IntersectionObserver API ,详见MDN:https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver,此时可以通过监听图片可滚动父元素的一些事件如 scroll、resize 等,然后通过一些 DOM 计算来判断图片元素是否进入可视区。
使用例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IntersectionObserver</title>
</head>
<body>
<div id="root" style="width: 700px; height: 1900px;">
<div class="label topLeft" style="background-color: red; width: 200px; height: 200px;"></div>
</div>
</body>
<script>
debugger
const intersectionObserver = new IntersectionObserver((entries) => {
// 如果 intersectionRatio 为 0,则目标在视野外,
// 我们不需要做任何事情。
if (entries[0].intersectionRatio <= 0) return;
console.log('Loaded new items');
});
// 开始监听
intersectionObserver.observe(document.querySelector(".topLeft"));
</script>
</html>