简介
无穷转动对我们来讲已经是很罕见的功用了,具体表现为当页面转动到某个位置时就自动加载数据,本文将讨论无穷转动的完成道理以及优化。
道理
我们先看看最简朴的无穷转动的例子:
function fetchData() {
fetch(path).then(res => doSomeThing(res.data));
}
window.addEventListener('scroll', fetchData);
上面就是无穷转动最简朴的例子啦~
实在就是监听 window
对象的 scroll
事宜,然后再触发猎取数据的函数~
但是,上面的例子中另有许多题目,个中最大的题目就是 猎取数据的函数(今后叫 fetch 函数)没有触发前提, 我们还须要不停优化,才在临盆环境下运用。
增加触发前提
我们先想一想,平常情况下,fetch 函数的触发前提有哪些呢 ?
在 fetch 过程当中不能反复触发
没有更多数据的时刻不能再触发
屏幕间隔容器边沿 xxx 的时刻触发
前两点很好处置惩罚,只需加个 isLoading
和 isEnd
的变量就能够了。
增加这两个变量以后,我们的代码就变成下面的模样啦:
var isLoading = false;
var isEnd = false;
function fetchData() {
if ( !isLoading && !isEnd ) {
isLoading = true;
fetch(path).then(res => {
isLoading = false;
res.data.length === 0 && isEnd = true;
doSomething(res.data);
});
}
}
window.addEventListener('scroll', fetchData);
第三点对不熟悉 DOM 的童鞋来讲就有点难度了~
盘算屏幕与容器边沿的间隔
我们以盘算屏幕底部与容器底部边沿为例:
如果有 api 能够直接获得元素底部与屏幕底部的间隔就最好啦,能够省去贫苦,但实际上并没有如许的 api。
但是,我们能够经由过程浏览器供应的两个 api,盘算出元素底部与屏幕底部之间的间隔。
第一个 api 是 window.innerHeight
,它返回的是屏幕(viewport)高度。
第二个 api 就是 Element.getBoundingClientRect
,这个要领用来盘算元素边沿与屏幕(viewport)之间的间隔。
须要提示一下,Element.getBoundingClientRect
会获得这么一个类 Object 对象:
ClientRect {
width: 760, // 元素宽度
height: 2500, // 元素高度
top: -1352, // 元素上边沿与屏幕上边沿的间隔
bottom: 1239, // 元素下边沿与屏幕上边沿的间隔
left: 760, // 元素左边沿与屏幕左边沿的间隔
right: 860 // 元素右边沿与屏幕左边沿的间隔
}
能够看看下面这图:
+------> +--------------------------------------------------------+
| | document.body |
| | |
| | |
body.getBoundingClientRect().top |
| | |
| | |
| +--------------------------------------------------------+
| | browser x |
+------> +--------------------------------------------------------+ <--+
| | window | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
window.innerHeight | |
| | | |
| | | |
| | body.getBoundingClientRect().bottom
| | | |
| | | |
| | | |
| | | |
| | | |
+------> +--------------------------------------------------------+ |
| | |
| | |
| | |
| | |
| | |
| | |
+--------------------------------------------------------+ <--+
有了这两个 api,我们很轻易就能够盘算出元素底部边沿与屏幕底部边沿的位置啦~
我们再修正下我们的代码:
var isLoading = false;
var isEnd = false;
var triggerDistance = 200;
function fetchData() {
var distance = container.getBoundingClientRect().bottom - window.innerHeight;
if ( !isLoading && !isEnd && distance < triggerDistance ) {
isLoading = true;
fetch(path).then(res => {
isLoading = false;
res.data.length === 0 && isEnd = true;
doSomething(res.data);
});
}
}
window.addEventListener('scroll', fetchData);
修正以后,当容器底部与屏幕底部间隔小于 200 的时刻,才会触发 fetch 函数,如许我们的无穷转动就越发有用啦!
支撑 window 之外的元素
但是,并非只要 window 才能够转动,具有高度的级块元素只需设置了 overflow: scroll
都是能够转动的。
我们须要再修正一下代码来让级块元素也支撑无穷转动!
function fetchData() { /* do something */ }
window.addEventListener('scroll', fetchData);
document.getElementById('container').addEventListener('scroll', fetchData);
很简朴吧!只须要为该容器元素增加一个 scroll 的事宜监听器就好啦!
出处
http://scarletsky.github.io/2016/04/20/how-to-implement-infinite-scroll/
参考资料
https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect