如果一个页面图片过多,刚进入页面就会加载多量的图片,图片也未必会看到,而且会对增加对服务器的压力,所以这里就这时候就用到了我们的图片懒加载
原理是监听滚动事件,计算位置是否到达可视区域,到达后就把img的src值设置为图片链接
//Vue 图片懒加载
var init = {
lazyLoad: false,
// 自定义默认图片
default: 'http://www.santaihu.com/e/data/tmp/titlepic/d69aff60d4b805ce53518d44aa45c831.jpg'
}
var listenList = [];
var imageCatcheList = [];
const isAlredyLoad = (imageSrc) => {
if (imageCatcheList.indexOf(imageSrc) > -1) {
return true;
} else {
return false;
}
}
//检测图片是否可以加载,如果可以则进行加载
const isCanShow = (item) => {
var ele = item.ele;
var src = item.src;
//图片距离页面顶部的距离
var top = ele.getBoundingClientRect().top;
//页面可视区域的高度
var windowHeight = window.innerHight;
//top + 20 已经进入了可视区域10像素
if (top + 20 < window.innerHeight) {
var image = new Image();
image.src = src;
image.onload = function () {
ele.src = src;
imageCatcheList.push(src);
listenList.remove(item);
}
return true;
} else {
return false;
}
};
const onListenScroll = () => {
window.addEventListener('scroll', function () {
var length = listenList.length;
for (let i = 0; i < length; i++) {
isCanShow(listenList[i]);
}
})
}
//Vue 指令最终的方法
const addListener = (ele, binding) => {
if (!Array.prototype.remove) {
Array.prototype.remove = function (item) {
if (!this.length) return
var index = this.indexOf(item);
if (index > -1) {
this.splice(index, 1);
return this
}
}
}
//绑定的图片地址
var imageSrc = binding.value;
//如果已经加载过,则无需重新加载,直接将src赋值
if (isAlredyLoad(imageSrc)) {
ele.src = imageSrc;
return false;
}
var item = {
ele: ele,
src: imageSrc
}
//图片显示默认的图片
ele.src = init.default;
//再看看是否可以显示此图片
if (isCanShow(item)) {
return
}
//否则将图片地址和元素均放入监听的lisenList里
listenList.push(item);
//然后开始监听页面scroll事件
onListenScroll();
}
export default {
inserted: addListener,
updated: addListener
}
然后在文件中引入
import copy from './copy'
import longpress from './longpress'
import throttle from './throttle'
import emoji from './emoji'
import lazyload from './lazyload'
// 自定义指令
const directives = {
copy,
longpress,
throttle,
emoji,
lazyload
}
export default (Vue)=>{
Object.keys(directives).forEach((key) => {
Vue.directive(key, directives[key])
})
}
然后再在main中引入就行
这样就可以使用了
<template>
<div class="main">
<div class="parent">
<div class="child">
<img class="lazyimg" v-lazyload='url' />
</div>
</div>
</div>
</template>
<script>
export default {
name: 'test',
data() {
return {
emoji: "",
url: 'http://www.santaihu.com/e/data/tmp/titlepic/f25f87010664b5393de14d15ef0d60b9.jpg'
}
},
methods: {
myClick() {
console.log('1231231')
},
longClick(e) {
console.log(e)
},
longClick2() {
console.log('无参数')
}
}
}
</script>
<style>
.main {
margin: auto auto;
height: 10px;
}
.parent {
}
.lazyimg {
height: 100px;
position: absolute;
bottom: 0;
}
.child {
width: 100%;
height: 2000px;
position: relative;
}
</style>
但是还有缺陷,可视区域是计算屏幕的可是区域,并非计算父节点的可视区域
需要源码的小朋友可以在这里下载