懒加载定义
图片懒加载其实就是延迟加载。也就是不用一次性加载所有的图片,等到用户需要某张图片的时候再加载,这样可以避免在同一时间请求大量的数据。也就是当图片滚动到可视区域的时候再去加载图片。
指令
Vue中除了平时常用的v-show、v-bind等指令外,还可以自定义指令。由于自定义指令过于简单,这里只是大致说一下用得到的钩子函数的作用。
bind:只调用一次,指令绑定到元素时调用,可以用来初始化。inserted:被绑定的元素插入到父节点时调用。
实现
在component文件夹中新建LazyLoad文件夹,在文件夹里新建index.js。
代码如下:
const LazyLoad = {
// install方法
install(Vue, options) {
// 代替图片的loading图
let defaultSrc = options.default;
Vue.directive('lazy', {
bind(el, binding) {
LazyLoad.init(el, binding.value, defaultSrc);
},
inserted(el) {
// 兼容处理
if ('IntersectionObserver' in window) {
LazyLoad.observe(el);
} else {
LazyLoad.listenerScroll(el);
}
},
})
},
// 初始化
init(el, val, def) {
// data-src 储存真实src
el.setAttribute('data-src', val);
// 设置src为loading图
el.setAttribute('src', def);
},
// 利用IntersectionObserver监听el
observe(el) {
let io = new IntersectionObserver(entries => {
let realSrc = el.dataset.src;
if (entries[0].isIntersecting) {
if (realSrc) {
el.src = realSrc;
el.removeAttribute('data-src');
}
}
});
io.observe(el);
},
// 监听scroll事件
listenerScroll(el) {
let handler = LazyLoad.throttle(LazyLoad.load, 300);
LazyLoad.load(el);
window.addEventListener('scroll', () => {
handler(el);
});
},
// 加载真实图片
load(el) {
let windowHeight = document.documentElement.clientHeight
let elTop = el.getBoundingClientRect().top;
let elBtm = el.getBoundingClientRect().bottom;
let realSrc = el.dataset.src;
if (elTop - windowHeight < 0 && elBtm > 0) {
if (realSrc) {
el.src = realSrc;
el.removeAttribute('data-src');
}
}
},
// 节流
throttle(fn, delay) {
let timer;
let prevTime;
return function (...args) {
let currTime = Date.now();
let context = this;
if (!prevTime) prevTime = currTime;
clearTimeout(timer);
if (currTime - prevTime > delay) {
prevTime = currTime;
fn.apply(context, args);
clearTimeout(timer);
return;
}
timer = setTimeout(function () {
prevTime = Date.now();
timer = null;
fn.apply(context, args);
}, delay);
}
}
}
export default LazyLoad;
使用
在main.js里添加
import LazyLoad from './components/LazyLoad';
Vue.use(LazyLoad, {
default: 'https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7f2421e0269d41299dad3ff4bd0dced9~tplv-k3u1fbpfcp-watermark.image?'
});
在组件中使用
<img v-lazy="'https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7f2421e0269d41299dad3ff4bd0dced9~tplv-k3u1fbpfcp-watermark.image?'" />
大功告成!以此类推可以自定义很多指令如v-permission等等