vue-lazyload自实现
vue学习 vue-lazyload组件的实现
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、vue-lazyload是什么?
实现图片懒加载
二、使用步骤
1.引入库
代码如下(示例):
import Vue from "vue";
import App from "./App.vue";
import MyLazLoad from "@/my-lazload";
Vue.config.productionTip = false;
Vue.use(MyLazLoad, {
loading:
"",
preload: 1,
});
new Vue({
render: (h) => h(App),
}).$mount("#app");
## 2.具体实现js代码部分
代码如下(示例):
```c
/*
懒加载效果,实际图片出现前加载默认图片
默认加载可视区域的图片 不显示部分的不加载
滚动图片 添加滚动监听
对外抛出不是一个类,外部没有实例化
preload预加载方式,相对可视区域高度的倍数
*/
function getScrollParent(el) {
//获取子元素绑定overf:scroll auto属性的父元素
let parent = el.parentNode;
while (parent) {
if (/(scroll)|(auto)/.test(getComputedStyle(parent)["overflow"])) {
return parent;
}
parent = parent.parentNode;
}
return null;
}
//同步加载图片
function asyncImgLoad(src, resove, reject) {
let img = new Image();
img.src = src;
img.onload = resove;
img.error = reject;
}
//对逻辑功能进行拆分
const MyLaz = (Vue) => {
//为了实现元素和对象的关联,创建一个绑定对象
class ReactiveListene {
constructor({ el, src, renderEl, preload }) {
this.el = el;
this.src = src;
this.renderEl = renderEl;
this.preload = preload;
this.state = { loading: false }; //还没有加载
}
//检测是不是在可视区域的范围内
checkInViem() {
let { top } = this.el.getBoundingClientRect();
return top < window.innerHeight * this.preload;
}
//加载图片的方法
load() {
//优先加载loading
this.renderEl(this, "loading");
//加载实际图片
asyncImgLoad(
this.src,
() => {
//图片加载成功后,渲染成功图片
// setTimeout(() => {
//延时器效果更加明显 方便观察
// this.state.loading = true;
// this.renderEl(this, "success");
// }, 1000);
this.state.loading = true;
this.renderEl(this, "success");
},
() => {
//图片加载失败后,渲染失败图片
this.renderEl(this, "error");
}
);
}
}
return class LazClass {
constructor(options) {
const { preload, loading } = options;
this.preload = preload || 1;
this.loading = loading;
// 绑定滚动事件初始
this.bindScrollEvent = false;
//保存所有元素
this.listenerArr = [];
}
handleScroll() {
// 滚动的监听事件
this.listenerArr.map((listener) => {
//验证是否加载
if (!listener.state.loading) {
let isInView = listener.checkInViem();
isInView && listener.load();
}
return listener;
});
}
add(el, bindings) {
//添加滚动监听
//将图片对应的listener对象存起来
Vue.nextTick(() => {
const scrollBox = getScrollParent(el);
if (scrollBox && !this.bindScrollEvent) {
this.bindScrollEvent = true;
scrollBox.addEventListener("scroll", this.handleScroll.bind(this));
}
//在绑定元素的时候添加检测对象
const listener = new ReactiveListene({
el,
src: bindings.value,
renderEl: this.renderEl.bind(this),
preload: this.preload,
});
this.listenerArr.push(listener);
//初始化触发
this.handleScroll();
});
}
// 渲染方法
renderEl(listener, state) {
let el = listener.el;
let src = "";
switch (state) {
case "loading":
src = this.loading;
break;
case "error":
src = "";
break;
default:
src = listener.src;
break;
}
el.setAttribute("src", src);
}
};
};
//注册自定义指令
const MyLazLoad = {
install(Vue, options) {
//创建自定义指令
const LazClass = MyLaz(Vue);
const laz = new LazClass(options);
Vue.directive("zby", {
//钩子函数bind:只调用一次,指令第一次绑定元素时调用,这儿可以进行一次初始化设置
bind: laz.add.bind(laz), //目的是调用add方法时候,this能够指向的是实例
});
},
};
export default MyLazLoad;
#APP.vue 部分
<template>
<div id="app">
<div class="box">
<ul>
<li v-for="(item, index) in list" :key="index">
<img v-zby="item.imgurl" alt="" />
</li>
</ul>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "App",
data() {
return {
list: [],
};
},
async mounted() {
const res = await axios.get("/fcj/music/getRecommendList");
this.list = res.data.data.list;
console.log(this.list);
},
};
</script>
<style lang="less">
.box {
width: 200px;
height: 400px;
border: 1px solid pink;
overflow: scroll;
li {
list-style: none;
width: 120px;
height: 120px;
img {
width: 100%;
height: 100%;
}
}
}
</style>
总结
仅供参考 谢谢