通常在开发商城列表页,或者相册的时候会有不少的图片请求,若是同时所有请求对服务器端的压力会比较大(不是只有你一我的),因此就有了图片的懒加载,懒加载意思就是只加载可视区域的图片git
大概思路是这样子的:github
1.滚动条的高度加上可视区域的高度 > 目标对象距离顶部的高度就意味在可视范围内。
window.scrollY + window.innerHeight > img.offsetTop
2.img的src属性使用一个空值,自定义一个属性data-src绑定真实图片url
3.当处于可视范围内的时候src绑定data-src的属性值
复制代码
// 基础版本当在可视范围内的时候就展现图片
class lazyLoad {
constructor () {
const imgs = document.getElementsByTagName('img')
// 获取到的是类数组,须要转换成数组类型,以便使用数组方法
this.imgs = Array.from([...imgs])
this.init()
}
// 方法一计算高度判断是否在视口内部
viewImage () {
let height = window.scrollY + window.innerHeight
this.imgs.forEach(img => {
if (img.offsetTop < height) {
const realURL = img.getAttribute('data-src')
// 版本一 为了表现明显点加个定时器
setTimeout(() => {
img.src = realURL
}, 200)
}
})
}
init () {
let that = this
// 版本一
window.onscroll = function () {
that.viewImage()
}
}
}
new lazyLoad()
复制代码
window绑定scroll事件,因为scoll事件触发评率极高,影响浏览器的性能,因此加一个节流300ms触发一次数组
// 简易版节流
function throttle(func, wait) {
var pre = 0
return function() {
var now = new Date()
var context = this
if (now - pre > wait) {
func.apply(context)
pre = now
}
}
}
init () {
let that = this
// 版本一
window.onscroll = throttle(function () {
that.viewImage()
}, 300)
}
复制代码
IntersectionObserver API能自动监听目标是否在可视区域内,这样子就不要判断高度了;浏览器
class lazyLoad {
constructor () {
const imgs = document.getElementsByTagName('img')
this.imgs = imgs
this.init()
}
viewImage () {
// start observing
for (let img of this.imgs) {
const intersectionObserver = new IntersectionObserver(function(entries) {
// If intersectionRatio is 0, the target is out of view
// and we do not need to do anything.
for(let entry of entries) {
if (entry.intersectionRatio <= 0) return
else {
const img = entry.target
const realURL = img.dataset.src
img.src = realURL
}
}
});
// 开始监听
intersectionObserver.observe(img)
}
}
init () {
this.viewImage()
}
}
new lazyLoad()
复制代码
IntersectionObserver的介绍,能够查看文档服务器
为了兼容低版本浏览器因此要结合两个版本:app
// 基础版本当在可视范围内的时候就展现图片
class lazyLoad {
constructor () {
const imgs = document.getElementsByTagName('img')
// this.imgs = Array.from([...imgs])
this.imgs = imgs
this.init()
}
// 方法一计算高度判断是否在视口内部
viewImage2 () {
let windowHeight = window.scrollY + window.innerHeight
this.imgs.forEach(img => {
if (img.offsetTop < windowHeight) {
const realURL = img.getAttribute('data-src')
// 版本一 为了表现明显点加个定时器
setTimeout(() => {
img.src = realURL
}, 200)
}
})
}
// 方法二利用API判断是否在视口内
viewImage () {
// start observing
for (let img of this.imgs) {
const intersectionObserver = new IntersectionObserver(function(entries) {
// If intersectionRatio is 0, the target is out of view
// and we do not need to do anything.
for(let entry of entries) {
if (entry.intersectionRatio <= 0) return
else {
const img = entry.target
const realURL = img.dataset.src
img.src = realURL
}
}
});
intersectionObserver.observe(img)
}
}
init () {
let that = this
// 判断是否支持IntersectionObserver
if ('IntersectionObserver' in window) {
that.viewImage()
} else {
window.onscroll = throttle(function () {
that.viewImage2()
}, 500)
}
}
}
new lazyLoad()
复制代码
到此一个简单版的图片懒加载就完成了。性能
动动手才能变强吧。ui
源码地址 github.com/wanghao1993…this