1.什么是图片懒加载
当一个组件或者是一个页面存在着大量的img标签,需要加载大量的图片,如果不使用懒加载处理图片,那么将在页面出现或者组件挂载的时候一次性加载完毕所有的图片,非常消耗性能,还有可能造成白屏时间过长,影响用户的体验感。那么经过懒加载处理的图片,只有当图片进入视口区域时,图片才会加载,避免了性能的浪费。
2.懒加载指令
Vue3写法,需要用到Vueuse函数库,非常方便,记得提前下载
//定义懒加载模块
import { useIntersectionObserver } from '@vueuse/core'
export const lazyPlugin = {
install(app){
app.directive('img-lazy',{
//el:指令绑定的元素
//binding:表达式的值
mounted(el,binding){
const {stop} = useIntersectionObserver(
el,
([{ isIntersecting }]) => {
if(isIntersecting){
//进入视口区域
el.src = binding.value
stop()
}
},
)
}
})
}
}
记得提前组件内引入或者全局注册,组件内使用
<img v-img-lazy="item.url">
第二种写法Vue2
// 图片懒加载
export const LazyLoad = {
install (Vue, options) {
// 代替图片的loading图
options = options || {}
const defaultSrc = require('../assets/loading.gif')
const Lazy = 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)
}
}
})
return Lazy
},
// 初始化
init (el, val, def) {
// data-src 储存真是src
el.setAttribute('data-src', val)
// 设置src为loading图
el.setAttribute('src', def)
},
// 利用IntersectionObserver监听el
observe (el) {
const io = new IntersectionObserver(entries => {
const readSrc = el.dataset.src
// 如果进入视口
if (entries[0].isIntersecting) {
if (readSrc) {
el.src = readSrc
el.removeAttribute('data-src')
}
}
})
io.observe(el)
},
// 监听scroll事件
listenerScroll (el) {
const handler = LazyLoad.throttle(LazyLoad.load, 300)
LazyLoad.load(el)
window.addEventListener('scroll', () => {
handler(el)
})
},
// 加载真实图片
load (el) {
const windowHeight = document.documentElement.clientHeight
const elTop = el.getBoundingClientRect().top
const elBtm = el.getBoundingClientRect().bottom
const 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) {
const currTime = Date.now()
const 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)
}
}
}
注册
import { throttle, debounce, LazyLoad } from './directive'
Vue.use(LazyLoad.install(Vue))
图片引入Vue2要使用require,否则直接写路径会报错