龙空技术网

图片懒加载实现

朝学朝用 189

前言:

眼前姐妹们对“h5图片懒加载”大概比较关注,大家都需要剖析一些“h5图片懒加载”的相关知识。那么小编在网络上搜集了一些有关“h5图片懒加载””的相关知识,希望同学们能喜欢,看官们一起来了解一下吧!

目前图片懒加载的方式主要有两种:

1、利用 getBoundingClientRect API得到当前元素与视窗的距离来判断

2、利用h5的新API IntersectionObserver 来实现

getBoundingClientRect

Element.getBoundingClientRect() 方法返回值是一个 DOMRect 对象,包含了该元素一组矩形的集合:是与该元素相关的css边框集合(top, left, right, bottom)。

我们可以采用如下方法来判断是否在可视区域:

isViewport (el) { const viewWidth = window.innerWidth || document.documentElement.clientWidth; const viewHeight = window.innerHeight || document.documentElement.clientHeight; let { top, left, right, bottom } = el.getBoundingClientRect() return ( top >= 0 && left >= 0 && right <= viewWidth && bottom <= viewHeight )}

getBoundingClientRect 方式来实现需要监听 scroll 方法来配合,对于浏览器的性能会有一定的问题。

IntersectionObserver

而 IntersectionObserver 方法是在2016年初提出来的,该API提供了一种异步观察目标元素相对与 root 元素是否进入了可视区域。作为一个新兴API,会有一定的兼容问题,点击查看兼容性。

当 IntersectionObserver 对象被创建,其被配置为监听根中一段给定比例的可见区域。一旦 IntersectionObserver 被创建,则无法更改其配置,所以一个给定的观察者对象只能用来监听可见区域的特定变化值,但是可以在同一个观察者对象中配置监听多个目标元素。

属性

root: 所监听对象的具体祖先元素。如果未传入值或值为null,则默认使用顶级文档的视窗。

rootMargin: 计算交叉时添加到根(root)边界盒bounding box的矩形偏移量, 可以有效的缩小或扩大根的判定范围从而满足计算需要。

thresholds: 可以是一个单独的number,也可以是一个number数组。当 root 元素与 target 元素相交达到该值的时候会执行回调。当值设定为1时,那么 target 元素有一个像素出现在 root 元素,回调就会执行;如果值设为1,那么就是当 target 元素完全出现在 root 元素当中才会执行。默认为0。如果当值设定为 [0, 0.25, 0.5, 0.75, 1] 时,那么每满足一个值就会回调一次。该值设定的时候不是复数,当取值的时候为复数:

var observer = new IntersectionObserver(_observer, { root : null, threshold: [] // 单数});observer.thresholds // 复数

方法

IntersectionObserver.disconnect: 停止所有监听工作

IntersectionObserver.observe: 开始监听一个目标元素

IntersectionObserver.takeRecords: 返回所有观察目标对象的数组

IntersectionObserver.unobserve: 停止监听特定目标元素。

下面添上图片懒加载 js 代码:

function LazyLoad (config) { this.default = { root: null, threshold: 0 } this.settings = Object.assign(this.default, config) this.images = [] this.observer = null this.init()}LazyLoad.prototype = { init () { if (!window.IntersectionObserver) { this.loadImages() return } this.images = document.querySelectorAll(this.settings.selector || '[data-src]') let _this = this let observeConfig = { root: this.settings.root, rootMargin: this.settings.rootMargin, threshold: [this.settings.threshold] } this.observer = new IntersectionObserver(changes => { Array.prototype.forEach.call(changes, entry => { if (entry.isIntersecting) { let target = entry.target _this.observer.unobserve(target) let src = target.dataset.src if (target.tagName.toLowerCase() === 'img') { target.src = src } else { target.style.backgroundImage = `url(${src})` } target.removeAttribute('data-src') } }) }, observeConfig) Array.prototype.forEach.call(this.images, image => { _this.observer.observe(image) image.src = _this.settings.placeholder }) }, loadImages () { let _this = this _this.replaceSrc() let hasDone = false function _scroll() { if (hasDone) return hasDone = true setTimeout(() => { _this.replaceSrc() hasDone = false }, 100) } window.onscroll = _scroll }, replaceSrc () { let _this = this let imgs = document.querySelectorAll(this.settings.selector || '[data-src]') Array.prototype.forEach.call(imgs, image => { if (!image.src) image.src = _this.settings.placeholder let src = image.dataset.src if (_this.isInnerView(image)) { if (image.tagName.toLowerCase() === 'img') { image.src = src } else { image.style.backgroundImage = `url(${src})` } image.removeAttribute('data-src') } }) }, isInnerView (el) { const viewWidth = window.innerWidth || document.documentElement.clientWidth; const viewHeight = window.innerHeight || document.documentElement.clientHeight; let { top, left, right, bottom } = el.getBoundingClientRect() return ( top >= 0 && left >= 0 && right <= viewWidth && bottom <= viewHeight ) }, destroy () { this.observer.disconnect(); }}

标签: #h5图片懒加载