Open
Description
本文实现一个基于Vue directive的Lazyload
实现
// throttle.js
const throttle = function (fn, delay = 200) {
let lastDate = 0; // 上次执行事件
return function () {
const context = this, argument = arguments;
const now = +new Date();
if (now - lastDate > delay) {
lastDate = now;
fn.apply(context, argument);
}
}
}
export default throttle;
// Lazyload.js
import throttle from '@/common/utils/throttle.js';
function replaceImgSrc(el, binding, vnode) {
const rect = el.getBoundingClientRect();
if (rect.top < document.documentElement.clientHeight) {
if (!el.src) {
el.src = binding.value;
// 图片加载完成后,将图片的高度变成原本的高度
let image = new Image();
image.onload = function () {
if (vnode.data.attrs && vnode.data.attrs.height) {
el.height = vnode.data.attrs.height;
} else {
el.height = image.height;
}
if (vnode.data.attrs && vnode.data.attrs.width) {
el.width = vnode.data.attrs.width;
}
}
image.src = binding.value;
}
}
}
function bindEvent(el, binding, vnode) {
replaceImgSrc(el, binding, vnode);
const throttleCb = throttle(replaceImgSrc, 200);
el.bindScrollListener = throttleCb.bind(this, el, binding, vnode);
document.addEventListener('scroll', el.bindScrollListener);
}
function _init(el, binding, vnode) {
el.height = (vnode.data.attrs && vnode.data.attrs.height) || 300; // 给图片定一个默认高度
el.width = (vnode.data.attrs && vnode.data.attrs.width) || document.documentElement.clientWidth;
}
export default {
bind(el, binding, vnode) {
_init(el, binding, vnode);
const vm = vnode.context;
if (vm._isMounted) {
bindEvent(el, binding, vnode);
}
vm.$on('hook:mounted', bindEvent.bind(this, el, binding, vnode));
},
unbind(el) {
document.removeEventListener('scroll', el.bindScrollListener);
}
}
// 在main.js中定义指令
import LazyLoad from './Lazyload/src/Lazyload';
Vue.directive('LazyLoad', LazyLoad);
// 使用
<template>
<ul class="lazy-load-example">
<li v-for="(item, index) in imgList" :key="index">
<img v-lazy-load="item" />
</li>
</ul>
</template>
Metadata
Assignees
Labels
No labels