图片的懒加载与预加载

懒加载:

懒加载:在需要的时候才加载图片,延迟加载甚至不加载图片。

作用: 延迟请求数或减少请求数,减轻了服务器压力,页面加载速度更快。

实现:

实现原理:创建一个自定义属性 data-src 存放真正需要显示的图片路径;当需要加载图片的时候,才获取到该图片的 data-src 的值赋给 src。

例如:有多张图片纵向排列显示,滚动到可视区域内才懒加载显示。

.lazyloadImg {
	width: 100%;
	// 图片懒加载必须要给图片设置高度。否则的话,图片加载完成之前,高度没有被撑开为 0,一加载进来所有图片都在可视区域内,将会全都加载出来
	height: 200px;
}
	
<div>
	<img class="lazyloadImg" data-src="https://img0.baidu.com/it/u=1345303087,1528317222&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1666198800&t=7eb134b9d7567021d3fbef74c31cbb6a" />
	<img class="lazyloadImg" data-src="https://img0.baidu.com/it/u=1088754973,1390499664&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1666198800&t=7e000c45a31f9aed7a303b81bdbc6539" />
	<img class="lazyloadImg" data-src="https://img0.baidu.com/it/u=3156137851,1307209439&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1666198800&t=66987b2f9f9d9b11ae6737a0d5323aab" />
	<img class="lazyloadImg" data-src="https://img0.baidu.com/it/u=4008146120,512111027&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1666198800&t=7566843c36c23fbc7930c2fc9e9b2ed7" />
	<img class="lazyloadImg" data-src="https://img2.baidu.com/it/u=1814268193,3619863984&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1666198800&t=54bb74703aba51ea4d514e9b011526f3" />
<div>
使用 getBoundingClientRect() 方法得到目标元素相对于视口左上角的坐标,再判断是否在视口之内。
// 图片懒加载的实现代码:

// DOM 元素是否在可视区域内
const windowHeight = window.innerHeight
const windowWidth = window.innerWidth
const isvisibleArea = el => {
	const rect = el.getBoundingClientRect()
	return rect.bottom > 0 && rect.top < windowHeight && rect.right > 0 && rect.left < windowWidth
}

const imgEls = [...document.querySelectorAll('.lazyloadImg')]
const lazyLoadImg = () => {
	for (let i = 0; i < imgEls.length; i++) {
		const imgEl = imgEls[i]
		if (isvisibleArea(imgEl)) {
	    	imgEl.src = imgEl.dataset.src
	    	 // 已经渲染过的就删除掉,避免重复请求
			imgEls.splice(i, 1)
			i--
	  }
	}
}
lazyLoadImg()
// 此处可使用防抖来优化 lazyLoadImg 的执行
// 此处不可使用节流。因为如果使用节流的话,一触发滚动,lazyLoadImg 就会开始执行一次,但此时元素还没进入可视区域,导致无法渲染出来
window.addEventListener('scroll', lazyLoadImg)
使用交叉观察器 IntersectionObserver:

IntersectionObserver 是浏览器原生提供的构造函数,可以自动观察元素是否可见。接受两个参数:callback 是可见性变化时的回调函数,option 是可选的配置对象。返回值是一个观察器实例。

var io = new IntersectionObserver(callback, option)

目标元素的可见性 visibity 变化时,就会调用观察器的回调函数 callback。callback 一般会触发两次。一次是目标元素刚刚进入视口(开始可见),另一次是完全离开视口(开始不可见)。callback 函数的参数 entries 是一个数组,每个成员都是一个IntersectionObserverEntry 对象,IntersectionObserverEntry 对象提供目标元素的信息,一共有六个属性。

var io = new IntersectionObserver(
  entries => {
    console.log(entries)
  }
)
{
   // IntersectionObserverEntry 对象的属性:
   // 可见性发生变化的时间,是一个高精度时间戳,单位为毫秒
  time: 3893.92,
  // 根元素的矩形区域的信息,getBoundingClientRect() 方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回 null
  rootBounds: ClientRect {
    bottom: 920,
    height: 1024,
    left: 0,
    right: 1024,
    top: 0,
    width: 920
  },
  // 目标元素的矩形区域的信息
  boundingClientRect: ClientRect {
     // ...
  },
 //目标元素与视口(或根元素)的交叉区域的信息
  intersectionRect: ClientRect {
    // ...
  },
  / /目标元素的可见比例,即 intersectionRect 占 boundingClientRect 的比例,完全可见时为 1,完全不可见时小于等于 0
  intersectionRatio: 0.54,
  // 被观察的目标元素,是一个 DOM 节点对象
  target: element
}

在这里插入图片描述
实例方法:

  1. observe():开始观察,可以指定观察哪个 DOM 节点。参数是一个 DOM 节点对象。如果要观察多个节点,就要多次调用这个方法。
  2. unobserve():停止观察。
  3. disconnect():关闭观察器。
// 图片懒加载的实现代码:
var observer = new IntersectionObserver(
    (entries) => {
        entries.forEach((entry) => {
            if (entry.intersectionRatio > 0) {
                var imgEl = entry.target
                imgEl.src = imgEl.dataset.src
                observer.unobserve(imgEl)
            }
        })
    }
)

const lazyLoadImg = () => {
	const imgEls = [...document.querySelectorAll('.lazyloadImg')]
	imgEls.forEach((imgEl) => {
	    observer.observe(imgEl)
	})
}
lazyLoadImg()

预加载:

预加载:提前加载图片,当用户需要查看时就可直接从本地缓存中读取。

如果图片在使用之前就已经请求过了,那么再次使用的时候,就不会再去请求了,而是直接从本地缓存中读取。

作用:能使用户的操作得到最快的反映,提升了用户体验。但是增加了服务器压力,首页加载时间变长。

实现:

CSS 实现:隐藏在 background 的 url 属性里面。

缺点:图片跟随文档一同加载,图片较多的时候会导致加载缓慢。

.preloadImg { 
	// 使用 background 属性加载图片,但是并不显示出来
	background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; 
}  
JS 实现:通过 JS 中的 Image 对象。
const preloadImg(imgUrls) {
	imgUrls.forEach(imgUrl => {
		const img = new Image()
		img.src = imgUrl
	})
}

var imgUrls = [
	'./imgsrc1',
	'./imgsrc2',
	'./imgsrc3',
];
preloadImg(imgUrls)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值