前言
图片懒加载原理
1.初始化src属性设置为默认图片(占位图片)
2 .img标签自定义一个属性存储图片真实url
3.监听页面滚动,当图片出现在可视区域把真实url赋值给src
前2步都很容易实现,第三步怎么判断图片是否出现在可视区域?
通过element.getBoundingClientRect()可获知图片顶部和底部分别距离可视区域顶部距离,假设
分别为elTop(图片顶部距离可视区域顶部距离),elBottom(图片底部距离可视区域顶部距离),windowHeight(可视区域高度),当满足elTop-windowHeight<0&&elBottom>0时图片刚好出现在可视区域内
当然也可以通过新兴的API IntersectionObserver判断是否出现在可视区域,兼容性不好这里就不采用了
代码实现
lazyLoadImage.js(自定义指令文件)
const lazyLoadImage = defaultImage => {
let windowHeight = document.documentElement.clientHeight || document.body.clientHeight//可视区域高
function throttle(fn, delay) {//节流
let timeout = null
return (...args) => {
if (timeout) return
timeout = setTimeout(() => {
fn.apply(this, args)
timeout = null
}, delay);
}
}
function loadImage(el) {//加载图片
return () => {
let top = el.getBoundingClientRect().top
let bottom = el.getBoundingClientRect().bottom
if (top - windowHeight < 0 && bottom > 0&&el.hasAttribute('data-src')) {//图片出现在可视区域内开始加载图片
el.src = el.getAttribute('data-src')
el.removeAttribute('data-src')
}
}
}
return {
bind(el, binding) {
el.src = defaultImage
el.setAttribute('data-src', binding.value)
},
inserted(el) {
loadImage(el)()//显示初始(首屏)图片
window.addEventListener('scroll', throttle(loadImage(el), 500))//每滚动500毫秒加载一次图片
}
}
}
const install = {
install(vue, defaultImage) {
//v-lazy
vue.directive('lazy', lazyLoadImage(defaultImage))
}
}
export default install
main.js
import lazyLoadImage from './directive/lazyLoadImage'
const defaultImage=require('@/assets/loading.gif')//默认占位图片
Vue.use(lazyLoadImage,defaultImage)
页面引用(v-lazy="真实url)"
<template>
<div class="page">
<img class="image" v-for="item in imageList" :key="item" v-lazy="item" />
</div>
</template>
export default {
data() {
return {
imageList: [
"https://xxxxxxxx1",
"https://xxxxxxxx2",
"https://xxxxxxxx3",
"https://xxxxxxxx4",
"https://xxxxxxxx5",
"https://xxxxxxxx6",
"https://xxxxxxxx7",
"https://xxxxxxxx8",
"https://xxxxxxxx9",
"https://xxxxxxxx10",
],
};
},