博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IntersectionObserver + Custom Elements 实现图片懒加载(滚动加载)/点击重试
阅读量:5959 次
发布时间:2019-06-19

本文共 2954 字,大约阅读时间需要 9 分钟。

前言

在我们实际业务开发过程中,经常需要用到图片懒加载,也就是滚动加载。其功能就是,如果图片在可视区域,则触发加载逻辑。

传统实现方式

我们传统的实现方式,则是通过监听scroll事件,通过计算元素的(height、width、offset)等,判断该元素是否在可视区域,然后出发加载动作。

通过这种实现方式有很多库或者demo代码,这就不重复多说了。

但是这种方式的弊端也很多,由于滚动过程中,会触发大量scroll事件,因此我们一般还会结合debounce,减少每次触发逻辑,提示性能。(每次获取元素的height、width、style等都会触发reflow,稍微不甚就会引起严重的性能问题)

现代浏览器实现方式

在现代浏览器通过IntersectionObserver则可以比较简单、优雅的实现。

IntersectionObserver

IntersectionObserver接口 (从属于Intersection Observer API) 提供了一种异步观察目标元素与其祖先元素或顶级文档视窗(viewport)交叉状态的方法。

can be used to understand the visibility and position of DOM elements relative to a containing element or to the top-level viewport. The position is delivered asynchronously and is useful for understanding the visibility of elements and implementing pre-loading and deferred loading of DOM content.

目前在Chrome支持比较不错,如果不需要考虑兼容性问题,则放开手脚去用。

通过IntersectionObserver把所有图片对象进行监听,当图像出现在可视区域,IntersectionObserver则会把可视区域的对象进行回调,这时候进行加载即可完成。从此不需要操心什么时候在可视区域,要怎么计算,要怎么提升性能。

TIPS:一旦图片加载完成,记得unobserve移除监听事件,提升性能。

IntersectionObserver懒加载图片的示例代码,网络上也很多,这就不重复写了。

但这不是我们的终极目标,我们目标是打造类似网易新闻、微信公众号那样,图片懒加载,而且加载失败还能点击重试。并且使用时候不需要硬编码,各种钩子才能使用。

IntersectionObserver + Custom Elements

通过使用IntersectionObserver + Custom Elements 轻松打造<img-lazy></img-lazy>组件,在需要用到地方直接替换原有<img/>,则自动有懒加载和点击重试的功能,方便、好用。

Custom Elements

Method of defining new HTML tags.

简单来说,这是一个实现自定义元素的API(类似Vue的Compont),但是这是浏览器标准。 兼容性如下:

注意,还有个旧的API:

registerElement已经从 Web 标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性。

不建议使用document.registerElement(),请使用customElements.define()

但是本文还是基于document.registerElement()实现,废话不说,上代码。

var io = new IntersectionObserver((entries) => {  entries.forEach((e) => {    if (e.intersectionRatio < 0.25) return    let el = e.target    // 加载图片    loadImage(el, el.getAttribute('src'))    el = null  })}, {  threshold: [0.5]})var loadImage = (root, url) => {  if (!url) return  let el = root.shadowRoot.querySelector('img')  // 把图片地址暂存,失败重试时候使用  el._url = url  var img = new Image()  img.onload = () => {    // 加载成功,清除引用,方便垃圾回收    el._url = null    el.onclick = null    el.src = url    img = null    el = null  }  img.onerror = () => {    // 如果加载失败,点击自动重试    el.onclick = function  () {      loadImage(root, this._url)    }    img = null    el = null  }  img.src = url  // 清除监听,失败了需要手动点击重试,不会再触发自动加载  io.unobserve(root)}const prototype = Object.create(HTMLElement.prototype, {  createdCallback: {    value () {      // 创建自定义元素,并且通过shadowRoot,展示真正的img      let root = this.createShadowRoot()      root.innerHTML = ''    }  },  attachedCallback: {    value () {      if (this.getAttribute('src')) {        io.observe(this)      }    }  },  // 移除的时候,自动取消监听  detachedCallback: {    value () {      io.unobserve(this)    }  },  // 当属性变更时候,重新监听  attributeChangedCallback: {    value (attrName, oldVal, newVal) {      if (attrName == 'src') {        io.observe(this)      }    }  }})document.registerElement('img-lazy', {  prototype: prototype})复制代码

最后

通过以上方式,打造了一个基于WebComponent的图片懒加载组件,哪里想用就用哪里,完全不用操心具体细节。

参考:

转载地址:http://hwfax.baihongyu.com/

你可能感兴趣的文章
15.6. HTML嵌入图片
查看>>
Could not find class &#39;XXX.activity‘&#39;, referenced from method &#39;YYYY&#39;
查看>>
I.MX6Q MfgTool2 ucl2.xml eMMC
查看>>
[家里蹲大学数学杂志]第425期一个定积分的计算
查看>>
ASP.NET Web API 应用教程(一) ——数据流使用
查看>>
Python系列干货之Python与设计模式!
查看>>
C# iTextSharp 生成 PDF
查看>>
【中亦安图】Systemstate Dump分析经典案例(8)
查看>>
Template Method(模板方法)模式
查看>>
Dynamic proxy (good-原创)
查看>>
【Redis】Java之Redis工具类
查看>>
算法系列15天速成——第十一天 树操作(上)
查看>>
MySQL中游标使用以及读取文本数据
查看>>
Kubernetes部署的最佳安全实践
查看>>
理解C语言——从小菜到大神的晋级之路(8)——数组、指针和字符串
查看>>
Windows Shellcode学习笔记——shellcode在栈溢出中的利用与优化
查看>>
关于多线程中使用SendMessage
查看>>
【云栖大会】阿里云移动云Apsara Mobile重磅发布 推出Cloud Native App全新研发范式...
查看>>
【PMP】Head First PMP 学习笔记 第九章 人力资源管理
查看>>
2015年末必备前端工具集
查看>>