Appearance
Image 加载优化
图片预加载
图片预加载是指在页面加载时提前加载图片,使其缓存在浏览器中,当用户需要查看图片时立即显示,不需要等待加载。
let image = new Image();
image.src = 'image.jpg';
.image {
background-image: url('image.jpg');
}
<link rel="preload" href="image.jpg" as="image">
图片懒加载
延迟加载图片,用户滚动到页面上特定位置时才加载图片。
<img data-src="https://xxx.jpg">
getBoundingClientRect
window.addEventListener('scroll', function() {
this.imgLoadFn()
})
imgLoadFn() {
let that = this
let imgGroups = document.getElementsByTagName('img')
let imgGroupLen = imgGroups && imgGroups.length
// 最后一张图片还没加载出来,说明需要懒加载
if (imgGroupLen && imgGroups[imgGroupLen - 1].getAttribute('data-src')) {
for (let i = 0; i < imgGroups.length; i++) {
let imgItem = imgGroups[i] || {}
if (imgItem.getAttribute('data-src')) {
that.loadImg(imgItem)
}
}
}
},
loadImg(el) {
// 获取窗口高度
let docHeight = document.documentElement.clientHeight
let boundingClientRect = el.getBoundingClientRect()
let bottom = boundingClientRect.bottom
let top = boundingClientRect.top
/* 当元素进入窗口时,才加载真实图片
bottom: 元素的下边到窗口上边的距离
top: 元素的上边到窗口上边的距离
*/
if (top < docHeight && bottom > 0) {
el.src = el.dataset.src
el.removeAttribute('data-src')
}
// top >= docHeight || bottom <= 0 // 不可见
}
IntersectionObserver
function query(selector) {
return Array.from(document.querySelectorAll(selector))
}
let observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
let target = entry.target
console.log(entry.intersectionRatio, entry.isIntersecting)
// 有时isIntersecting可见,intersectionRatio却为0,修复一下
if ((entry.intersectionRatio > 0 && entry.intersectionRatio <= 1) ||
(entry.intersectionRatio === 0 && entry.isIntersecting)) {
if (target.dataset.src) {
// dataset.src 就是 获取 "data-src" 属性值
target.src = target.dataset.src
target.removeAttribute('data-src')
// 图片已加载, 解除观察
observer.unobserve(target)
} else {
observer.unobserve(target)
}
}
})
}, { threshold: [0] }) // 默认
query('img').forEach(function(item) {
// 观察每个图片对象
observer.observe(item)
})
第三方插件 vue-lazyload
import Vue from 'vue'
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload, {
preLoad: 1.3,
error: 'dist/error.png',
loading: 'dist/loading.gif',
attempt: 3 // 默认,尝试加载次数
})
<div v-for="(item, index) in imgList" :key="index">
<img v-lazy="item">
</div>