关于前端:实战用原生的-JavaScript-Intersection-Observer-API-实现-Lazy-Loading

51次阅读

共计 3683 个字符,预计需要花费 10 分钟才能阅读完成。

作者:神 Q 超人
译者:前端小智
起源:medium

有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。

前一阵子在做一个我的项目的时候,因为每组数据都要先通过很宏大的计算,才把计算后的后果 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')
);
  1. 先用循环产生 200 笔的假数据
  2. 写一个 render 的办法,把还没载入的数据循环加去,这里一次加 50 笔数据
  3. render 内加完数据,去判断以后加到的 index 有没有大于数据总数,如果有的话代表所有数据显示完了,因而暗藏 loading,并移除 Intersection Observer API 对 loading 的监听
  4. 毕竟一开始画面上还是要有数据!所以先手动执行第一次 render 办法
  5. 用 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/%…

交换

有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。

本文 GitHub https://github.com/qq44924588… 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。

正文完
 0