本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
图片懒加载效果
自定义了一个指令 Lazy
主要思想,图片如何加载当然要涉及,监听页面的滚动(事件总线),当图片这个元素的位置,在视口区域中的时候加载真实图片; 当没有在视口范围内时,就默认一个图片。
- 用自定义事件中的钩子函数,当自定义指令与元素绑定的时候,获取元素,以及 binging 对象。然后以对象的形式存储在一个数组中
- 这个数组,当我们切换页面的时候由于 Lazy 绑定了新的 img,你们数组就会在之前的基础上增加,也就是上一页的数据依然存在,然而我们不应该加载上一页的数据,所以我们就想到了用钩子函数
unbind()当元素与指令解绑也就是元素销毁时(那么显然就是不存在与当前页面中),将其在数组中去掉。- 要判断图片需不需要加载就是需要循环数组,获取其中对象的距离视口的值,在一定区域内的图片就需要加载,将处理完成的 dom 去除。最后,这里
new Image()是因为 Image 实例中有 onload 事件,在真实的图片加载完成时触发,将恢复真实的图片,
// 导入事件总线
import eventBus from "@/eventBus.js";
// 做一个防抖
import { debounce } from "@/utils";
import defaultGif from "@/assets/default.gif";
// 用一个数组来存储dom
let imgs = [];
function setImage(img) {
// 处理图片,
img.dom.src = defaultGif; //全部用默认的图片
//看dom是否在一定区域之内
// 视口高度
const clientHeight = document.documentElement.clientHeight;
const range = img.dom.getBoundingClientRect();
const height = range.top || 100;
if (range.top >= -height || range.top < clientHeight) {
// 在视口范围
const tempImage = new Image();
tempImage.onload = function () {
// 当真实图片加载完成后
img.dom.src = img.src;
};
tempImage.src = img.src;
// 加载完成就在数组中移除
imgs.filter((i) => {
return i !== img;
});
}
}
// 再监听到页面的滚动事件,调用该函数来加载应该显示的图片
function setImages() {
// 循环数组找到当中符合一定区域内的dom,
for (const img of imgs) {
setImage(img);
}
console.log("senf");
}
function handleScroll() {
setImages();
}
// 监听事件,并且对事件监听到了之后作出处理
eventBus.$on("mainScroll", debounce(handleScroll, 250));
export default {
inserted(el, bingding) {
const img = {
dom: el,
src: bingding.value,
};
imgs.push(img);
// 这里用来处理,一开始还没有滚动事件发生的时候,
// 就需要对图片做一个处理
setImage(img);
},
unbind(el) {
// 当指令与元素解绑也就是元素消失的时候,讲数组中不等于解绑元素的dom保留,解绑了就去掉
imgs = imgs.filter((img) => {
return img.dom != el;
});
},
};