原生JS Intersection Observer API实现懒加载

目录
  • 引言
    • Intersection Observer API
    • 使用方法
    • Lazy Loading

引言

前一阵子在做一个项目的时候,因为每组数据都要先通过很庞大的计算,才把计算后的结果 Render 到页面上,但这样就导致如果单页查出来的数据超过大概 5 笔,就会需要等待一段有感的时间,才能看到结果出现在画面上。

后来为了解决这差劲用户体验,就使用到的标题上说到的 Lazy Loading 来处理。简单说就是,虽然要显示的数据量有 10 笔,但因为一个页面大概只能呈现 2 到 3 笔,那我就先计算那 2 到 3 笔数据然后显示就好,剩下的数据等使用者往下滚再继续显示,这样等待时间就不会太久。

然后身为一个前端工程师,再想到这个解法以后,当然就是上 Github 找一个简单又方便的组件来解决它 ,而最后找到的 vue-scroll-loader 使用起来非常容易,代码也少少的,所以就在处理完 issue 后,看它内部是如何实现 Lazy Loading,于是就看到今天主要讲的 Intersection Observer API 啦!

Intersection Observer API

那 Intersection Observer API 到底是什麽?为什麽它可以用来实现 Lazy Loading 呢?以 MDN 的说法来说:

Intersection Observer API 提供了一种异步检测目标元素与祖先元素或 viewport 相交情况变化的方法。

简单说的意思就是只要使用 Intersection Observer API,就能够监听目标的元素在画面上出现或离开的时候,执行你交给它的 callback 方法。下方就来看看使用的方式吧!

使用方法

首先要有简单的 HTML 和 CSS,主要目标就是把 div 放在往下滚才会出现的地方:

body {
  height: 1000px;
}
.box {
  width: 100px;
  height: 100px;
  background: #000;
  position: absolute;
  top: 500px;
}
<body>
  <div class="box"></div>
</body>

接著我们用 Intersection Observer API 的 observe 方法,把要监听的 div 当作参数传给它,并用 callback 让它可以在 div 出现和离开的时候给个消息:

const intersectionObserver = new IntersectionObserver(
  () => { console.log('hi'); }
);
intersectionObserver.observe(
  document.querySelector('.box')
);

执行的结果就会像这样子:

而 Intersection Observer API 在执行 callback 的时候,也会给你一个 ArrayArray 是所有正在监听的元素,我们可以从这些元素里的 isIntersecting 来判断当前的元素是出现在画面中,还是离开画面了:

const intersectionObserver = new IntersectionObserver(
  (entries) => {
    if (entries[0].isIntersecting) {
      console.log('我進來了!');
    } else {
      console.log('我又出去了!');
    }
  }
);
intersectionObserver.observe(
  document.querySelector('.box')
);

执行结果:

最后就是当你不再需要继续监听元素的时候,可以使用 unobserve 来解除监听,使用时就像监听用的 observe 一样,给它不需要再监听的元素:

intersectionObserver.unobserve(
  document.querySelector('.box')
);

以上就是 Intersection Observer API 的基本用法,当然还有其他比较仔细的设置(可以看MDN 的介绍),但如果要完成一个简单的 Lazy Loading,那只要会上方的几种使用方式就绰绰有馀了!

Lazy Loading

Intersection Observer API 实现 Lazy Loading 的方法就是在数据列表的最后放个 loading 的小动画,接着只要去监听小动画,当它出现在页面中的时候,用 Intersection Observer API 的 callback 载入更多数据。

首先一样先简单写个要显示数据的 <ul>,和要监听的元素,这裡我就不做小动画了,直接用 Loading… 文字代替 :

<body>
  <ul class="list"></ul>
  <div class="loading">Loading...</div>
</body>

要注意监听的元素必须要在载入数据的最下面哦!不然它不会被监听到“出现在页面上”了(这个下方会更详细说明注意事项)。

JavaScript 的部分先贴代码,下方再来解释:

const data = Array.from(Array(200)).map(
  (_value, index) => `第 ${index + 1} 筆資料`
);
const render = () => {
  const list = document.querySelector('.list');
  const LOAD_DATA_COUNT = 50;
  const startLoadIndex = list.childNodes.length;
  const endLoadIndex = startLoadIndex + LOAD_DATA_COUNT;
  for (let i = startLoadIndex; i < endLoadIndex; i++) {
    if (data[i]) {
      const text = document.createTextNode(data[i]);
      const li = document.createElement('li');
      li.appendChild(text);
      list.appendChild(li);
    }
  }
  if (endLoadIndex >= data.length) {
    const loading = document.querySelector('.loading');
    loading.style.display = 'none';
    intersectionObserver.unobserve(loading);
  }
};
render();
const intersectionObserver = new IntersectionObserver(
  (entries) => {
    if (entries[0].isIntersecting) {
      setTimeout(render, 1000);
    }
  }
);
intersectionObserver.observe(
  document.querySelector('.loading')
);
  • 先用循环产生 200 笔的假数据
  • 写一个 render 的方法,把还没载入的数据循环加去,这里一次加 50 笔数据
  • 在 render 内加完数据,去判断当前加到的 index 有没有大于数据总数,如果有的话代表所有数据显示完了,因此隐藏 loading,并移除 Intersection Observer API 对 loading 的监听
  • 毕竟一开始画面上还是要有数据!所以先手动执行第一次 render 方法
  • 用 Intersection Observer API 监听 loading,只要一出现在画面上(代表使用者看完目前的数据,就要在执行 render。这裡为了有真正 render 的感觉,我用 setTimeout 来延迟 1 秒

执行的效果就会像这样子:

但是还有一点要注意的地方,以上方的例子来说,如果 Intersection Observer API 因为 loading 出现在页面中执行了 render,但是 render 后的数据量却不足以把 loading 移到画面外,那 loading 就会一直停留在画面中,而不是“出现在画面中”,这麽一来,Intersection Observer API 也就不会触发 render 载入更多数据。

最后来看一下支持情况。ntersection Observe API 的支持度算不错了,但如果产品有要考虑到 IE 的客户群就没办法用了。

最后还是觉得从开源项目里面以学到很多有趣的东西,也推荐大家可以在使用某些组件时候偷看一下背后的源码怎麽处理的。

~完,我是刷碗智,新的一年,我们一起洗刷刷新!!

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

原文:https://medium.com/starbugs/%...

以上就是原生JS Intersection Observer API实现懒加载的详细内容,更多关于JS Intersection Observer API懒加载的资料请关注我们其它相关文章!

(0)

相关推荐

  • JS实现图片懒加载(lazyload)过程详解

    对于图片较多的页面,使用懒加载可以大幅提高页面加载速度,提高用户体验. 懒加载的意义(为什么要使用懒加载) 对页面加载速度影响最大的就是图片,一张普通的图片可以达到几M的大小,而代码也许就只有几十KB.当页面图片很多时,页面的加载速度缓慢,几S钟内页面没有加载完成,也许会失去很多的用户. 所以,对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载.这样子对于页面加载性能上会有很大的提升,也提高了用户体验. 原理

  • 使用jpa的实体对象转json符串时懒加载的问题及解决

    目录 解决转json符串时懒加载问题方法(1) 解决转json符串时懒加载问题方法(2) Rest风格中关于JPA使用懒加载的坑 解决转json符串时懒加载问题方法(1) 1.导入hibernate5转json的Maven依赖: <dependency>     <groupId>com.fasterxml.jackson.datatype</groupId>     <artifactId>jackson-datatype-hibernate5</a

  • 利用原生JS实现懒加载lazyLoad的三种方法总结

    目录 前言 Method 1: 高度对比 Method 2: 使用getBoundingClientRect() 的API Method 3: 采用最新的 IntersectionObserver 构造函数 总结 前言 首先我们先搭建好页面如下: <style> * { padding: 0%; margin: 0%; } .contain img { width: 600px; height: 400px; } ul { list-style: none; } li { display: i

  • JavaScript懒加载详解

    目录 懒加载 CSS样式: HTML部分: script部分 : 总结 懒加载 顾名思义比较懒,不想全部加载出来,当用户什么时候想看我在加载后面的东西 概括:懒加载其实就是延时加载,即当对象需要用到的时候再去加载. 实现原理: 首先你要有很多个第一张用来加载的图片,加载完毕之后显示后面所需的图片 步骤实现: 1.加载load图片 2.判断哪些图片要加载 3.隐形加载图片 4.替换真图片 CSS样式: <style> img { width: 400px; height: 300px; disp

  • 一文搞懂JavaScript如何实现图片懒加载

    目录 实现思路 准备知识 data-* getBoundingClientRect() throttle window.innerHeight 完整代码 js部分 CSS部分 运行结果 总结 图片懒加载,往往作为减少首页白屏时间的一个解决方案而出现.直观的来说,就是不要直接加载所有图片,而是满足一定条件后才加载,也就是”惰性加载“.实现图片懒加载的方式有很多,如果要简单点那就直接使用第三方插件:vue-lazyload,如果想探究一下别人的插件是怎么实现图片懒加载的,那么可以看看本文是如何实现的

  • javascript实现图片预加载和懒加载

    本文实例为大家分享了javascript实现图片预加载和懒加载的具体代码,供大家参考,具体内容如下 预加载 预加载是预先加载好后面需要用到的资源, 后面使用的时候直接去缓存里取.举个栗子, 比如一个网站的开场动画, 这些动画是由很多图片组成的, 假如不预先加载好, 那就会造成动画不流畅产生闪动白屏.图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,保证了图片快速.无缝地发布,使用户在浏览你网站内容时获得更好的用户体验. //这里我把图片数量写死了,而且对图片名也有要求必须是阿拉伯数字后缀

  • 原生JS Intersection Observer API实现懒加载

    目录 引言 Intersection Observer API 使用方法 Lazy Loading 引言 前一阵子在做一个项目的时候,因为每组数据都要先通过很庞大的计算,才把计算后的结果 Render 到页面上,但这样就导致如果单页查出来的数据超过大概 5 笔,就会需要等待一段有感的时间,才能看到结果出现在画面上. 后来为了解决这差劲用户体验,就使用到的标题上说到的 Lazy Loading 来处理.简单说就是,虽然要显示的数据量有 10 笔,但因为一个页面大概只能呈现 2 到 3 笔,那我就先

  • 基于纯JS实现多张图片的懒加载Lazy过程解析

    一.效果图如下 上面的效果图,效果需求如下 1.还没加载图片的时候,默认显示加载图片背景图 2.刚开始进入页面,自动加载第一屏幕的图片 3.下拉界面,当一张图片容器完全显露出屏幕,即刻加载图片,替换背景图 4.加载图片的时候,有渐进显示图片效果 二.难点 1)如何Ajax请求数据 2)如何动态将json数据绑定到html中. 3)如何通过对图片的定位计算,触发图片懒加载机制 4)加分项,显示图片时有渐现的过渡动画 三.前期知识点 1)Ajax相关知识,XMLHttpRequest对象,所有现代的

  • JavaScript实现图片懒加载的方法分析

    本文实例讲述了JavaScript实现图片懒加载的方法.分享给大家供大家参考,具体如下: 懒加载是非常实用的提升网页性能的方式,当访问一个页面的时候,只显示可视区域内的图片,其它的图片只有出现在可视区域内的时候才会被请求加载. 我们现在用原生的js实现简单的图片懒加载,主要利用的原理就是先不给设置src,而是把图片的路径放在data-src中,等待图片被加载的时候将路径取出放到src中. HTML代码 <div class="container"> <div clas

  • webpack4 SCSS提取和懒加载的示例

    本节课讲解在webpack v4中的 SCSS 提取和懒加载.值得一提的是,v4和v3在 Scss 的懒加载上的处理方法有着巨大差别. >>> 本节课源码 >>> 所有课程源码 1. 准备工作 关于 SCSS 处理的基础,请参考webpack4 处理 SCSS. 本节课主要涉及 SCSS 在懒加载下提取的相关配置和插件使用. 下图展示了这次的目录代码结构: 为了实现 SCSS 懒加载,我们使用了extract-text-webpack-plugin插件. 需要注意,在安

  • 原生JS实现图片懒加载之页面性能优化

    在项目开发中,我们往往会遇到一个页面需要加载很多图片的情况.我们可以一次性加载全部的图片,但是考虑到用户有可能只浏览部分图片.所以我们需要对图片加载进行优化,只加载浏览器窗口内的图片,当用户滚动时,再加载更多的图片.这种加载图片的方式叫做图片懒加载,又叫做按需加载或图片的延时加载.这样做的好处是:1.可以加快页面首屏渲染的速度:2.节约用户的流量. 一.实现思路 1.图片img标签自定义一个属性data-src来存放真实的地址. 2.当滚动页面时,检查所有的img标签,判断是否出现在事业中,如果

  • 原生JS实现图片懒加载(lazyload)实例

    前言 图片懒加载也是比较常见的一种性能优化的方法,最近在用vue做一个新闻列表的客户端时也用到了,这里就简单介绍下实现原理和部分代码. 实现原理 加载页面的时候,图片一直都是流量大头,针对图片的性能方法也挺多的比如base64.雪碧图等:懒加载也是其中一种,主要原理是将非首屏的图片src设为一个默认值,然后监听窗口滚动,当图片出现在视窗中时再给他赋予真实的图片地址,这样可以保证首屏的加载速度然后按需加载图片. 具体代码 首先在渲染时,图片引用默认图片,然后把真实地址放在data-*属性上面. <

  • JS图片懒加载库VueLazyLoad详解

    目录 背景 说明 实现原理 1. placeholder 的实现很细致和灵活 2. 添加图片缓存 3. 事件监听使用节流 4. 监听事件不止滚动事件 5. 事件列队的方式来处理懒加载 6. 支持 data-srcset 7. 自定义控制可视区的判定范围 待完善 1. 没有解决布局抖动 2. 跳过已经加载图片的判断方式 3. 局部懒加载 4. 性能不是很好 5. observer 模式配置简单 6. SEO 不友好 总结 背景 上篇<图片懒加载原理方案详解>中详细解析了图片懒加载的原理和方案.主

  • 原生+React实现懒加载(无限滚动)列表方式

    目录 应用场景 效果预览 思路剖析 原生代码实现 迁移到React 总结 应用场景 懒加载列表或叫做无限滚动列表,也是一种性能优化的方式,其可疑不必一次性请求所有数据,可以看做是分页的另一种实现形式,较多适用于移动端提升用户体验,新闻.资讯浏览等. 效果预览 思路剖析 设置临界元素,当临界元素进入可视范围时请求并追加新数据. 根据可视窗口和滚动元素组建的关系确定数据加载时机. container.clientHeight - wrapper.scrollTop <= wrapper.client

  • 快速实现JS图片懒加载(可视区域加载)示例代码

    js懒加载图片 如何提高网页加载速度?在网页中有许多img标签,这些标签就是图片,其属性src则是指向服务器地址,当浏览器从上往下读取到src标签中的地址时,浏览器就会开启线程,加载这张图片.而并不是等到整张页面都解析完成才加载图片.我们要做的就是加载用户可视范围内的图片. js懒加载图片的目的 1.网页优化,提高网页加载速度 2.页面优化友好,提高SEO收录与排名 3.提高用户体验,减少服务器压力 实例代码如下: <!DOCTYPE html> <html lang="en&

随机推荐