效果
文章列表的图片懒加载, 只要图片位于视口位置就会加载图片, 否则显示默认图片
实现
1. 使用指令进行懒加载
如果为图片设置src,浏览器会自动地获取图片,使用指令给图片加一层处理
// 创建一个v-lazy的指令, 图片就可以使用它实现懒加载
import vLazy from "./directives/lazy";
Vue.directive("lazy", vLazy);
2. 使用指令周期钩子函数对数据处理
// 到处两个钩子对象
// 当被绑定元素插入父节点时使用,记录dom 和真实的src
export default {
inserted: function(el, binding) {
const img = {
dom: el,
src: binding.value,
};
imgs.push(img);
setImage(img);
},
// 当元素解绑时处理记录的imgs,清空
unbind: function(el) {
// img.dom ===el 是等于的,会返回true,但是unbind要清除狗子函数,所有要!==
imgs = imgs.filter((img) => img.dom !== el);
},
};
3. 单个img的视口边界判定setImage(img)
为一个函数,接受一个img对象, 判断是否位于视口,是的话就加载图片
function setImage(img) {
// 统统设置为默认图片
img.dom.src = defaultGif;
const clientHeight = document.documentElement.clientHeight;
const rect = img.dom.getBoundingClientRect();
const height = rect.height || 150;
//rect.top>=-height 是用来判断是否部分在视口范围内的
if (rect.top >= -height && rect.top <= clientHeight) {
const tempImg = new Image();
tempImg.onload = () => {
img.dom.src = img.src;
// 图片加载完成对imgs处理,已处理的清除掉
imgs = imgs.filter((i) => i !== img);
};
tempImg.src = img.src;
}
}
4. 事件总线处理scroll 懒加载
步骤3的 setImage
对单个img 的懒加载处理,
事件总线监听scroll
触发懒加载
// 防抖处理
eventBus.$bus.$on("mainScroll", debounce(handleScroll, 50));
function handleScroll() {
setImages();
}
//循环所有img进行懒加载处理
function setImages() {
for (const img of imgs) {
setImage(img);
}
}
感想
- 数据分为已处理和未处理时,直接将已处理的数据从这个数据里删除
- 数据每次获取了, 如果重新加载又会重新获取需要清理操作,清除之前的数据