如何仅在没有 jquery 的情况下使用 javascript 进行无限滚动
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22268079/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to do infinite scrolling with javascript only without jquery
提问by Arnold
I wish to implement infinite scrolling with javascript and without jquery.
我希望使用 javascript 和不使用 jquery 实现无限滚动。
I am new to javascript.
我是 javascript 新手。
After searching all over the net, I have this code.
在网上搜索后,我有这个代码。
<!DOCTYPE html><html lang="en"><head><title>scrolling</title>
<style>
.page {height: 900px;border:solid 1px #ccc}
</style>
</head>
<body>
<div id="scrollcontent">
<div class="page"></div>
</div>
<script>
//########################
function getScrollXY() {
var scrOfX = 0, scrOfY = 0;
if( typeof( window.pageYOffset ) == 'number' ) {
//Netscape compliant
scrOfY = window.pageYOffset;
scrOfX = window.pageXOffset;
} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
//DOM compliant
scrOfY = document.body.scrollTop;
scrOfX = document.body.scrollLeft;
} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
//IE6 standards compliant mode
scrOfY = document.documentElement.scrollTop;
scrOfX = document.documentElement.scrollLeft;
}
return [ scrOfX, scrOfY ];
}
function getDocHeight() {
var D = document;
return Math.max(
D.body.scrollHeight, D.documentElement.scrollHeight,
D.body.offsetHeight, D.documentElement.offsetHeight,
D.body.clientHeight, D.documentElement.clientHeight
);
}
document.addEventListener("scroll", function (event) {
if (getDocHeight() == getScrollXY()[1] + window.innerHeight)
{
var oldcontent = document.getElementById('scrollcontent');
oldcontent.innerHTML = oldcontent.innerHTML + '<div class="page">new content loaded</div>';
document.getElementById("scrollcontent").innerHTML=oldcontent.innerHTML;
}
});
</script>
</body>
</html>
However, this code works only when the scrollbar touches the bottom.
但是,此代码仅在滚动条触及底部时才有效。
I wish it to work when the user is 100 pixels from the bottom. (or near the bottom)
我希望它在用户距离底部 100 像素时工作。(或靠近底部)
I also need the code to work in most of the modern browsers, mobile devices etc.
我还需要代码在大多数现代浏览器、移动设备等中工作。
Also, is there any way to improve this code? Please suggest.
另外,有什么办法可以改进这段代码吗?请建议。
If there are any errors in the code, please correct.
如果代码中有任何错误,请更正。
Thank you
谢谢
采纳答案by Zafar
What about replacing this line of code:
替换这行代码怎么样:
if (getDocHeight() == getScrollXY()[1] + window.innerHeight)
with the following:
具有以下内容:
if (getDocHeight() - 20 <= getScrollXY()[1] + window.innerHeight)
Where 20
is the number how much px
s from bottom you want the trigger to execute.
哪里20
是多少怎么数量px
从底部是你想要触发执行。
回答by webpapaya
first of all i don't think that you have to support netscape and ie6 anymore. So with that in mind I created following script
首先,我认为您不必再支持 netscape 和 ie6。所以考虑到这一点,我创建了以下脚本
document.addEventListener("scroll", function (event) {
checkForNewDiv();
});
var checkForNewDiv = function() {
var lastDiv = document.querySelector("#scroll-content > div:last-child");
var lastDivOffset = lastDiv.offsetTop + lastDiv.clientHeight;
var pageOffset = window.pageYOffset + window.innerHeight;
if(pageOffset > lastDivOffset - 20) {
var newDiv = document.createElement("div");
newDiv.innerHTML = "my awesome new div";
document.getElementById("scroll-content").appendChild(newDiv);
checkForNewDiv();
}
};
also see jsfiddle
另见jsfiddle
回答by Zach Saucier
I use requestAnimationFrame
instead of listening for scroll. I also added a throttle based on time so it doesn't overwork our page and batched the element additions:
我使用requestAnimationFrame
而不是监听滚动。我还根据时间添加了一个节流阀,这样它就不会过度使用我们的页面并批量添加元素:
var numElementsToAdd = 10,
offsetForNewContent = 20;
function checkInfiniteScroll(parentSelector, childSelector) {
var lastDiv = document.querySelector(parentSelector + childSelector),
lastDivOffset = lastDiv.offsetTop + lastDiv.clientHeight,
pageOffset = window.pageYOffset + window.innerHeight;
if(pageOffset > lastDivOffset - offsetForNewContent ) {
for(var i = 0; i < numElementsToAdd; i++) {
var newDiv = document.createElement("div");
newDiv.innerHTML = "my awesome new div";
document.querySelector(parentSelector).appendChild(newDiv);
}
checkInfiniteScroll(parentSelector, childSelector);
}
};
var lastScrollTime = Date.now(),
checkInterval = 50;
function update() {
requestAnimationFrame(update);
var currScrollTime = Date.now();
if(lastScrollTime + checkInterval < currScrollTime) {
checkInfiniteScroll("#scroll-content", "> div:last-child");
lastScrollTime = currScrollTime;
}
};
update();
#scroll-content > div {
background: #c0c0c0;
height: 40px;
margin-bottom: 5px;
}
<div id="scroll-content">
<div>test div</div>
</div>
Demo
演示
回答by Vishaa
I used scrollHeight, scrollTop and clientHeight attribute of the element to find whether the scroll hit the bottom. Here is my code. I hope it helps.
我使用元素的 scrollHeight、scrollTop 和 clientHeight 属性来查找滚动是否到达底部。这是我的代码。我希望它有帮助。
Click here for more information.
Image describing scrollHeight, scrollTop and clientHeight.
描述 scrollHeight、scrollTop 和 clientHeight 的图像。
<html>
<head>
<title>Infinite Scroll</title>
</head>
<body>
<h3>Infinite Scroll Example</h3>
<div id="scrollContent" style="overflow-y: scroll; height: 100px; width: 500px">
<div style="height: 300px; background-color: red">
</div>
<div>
</body>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded',function () {
var elm = document.getElementById('scrollContent');
elm.addEventListener('scroll',callFuntion);
function callFuntion(){
var scrollHeight = elm.scrollHeight;
var scrollTop = elm.scrollTop;
var clientHeight = elm.clientHeight;
if(scrollHeight-scrollTop == clientHeight){
elm.innerHTML += '<div style="height: 300px; background-color: blue"> New Element Added </div>' ;
}
}
});
</script>
</html>
回答by Vasil Popov
Why whout jQuery? Some of the native properties like window.outerHeight actually can return not accurate results on some browsers. jQuery fixes that so you can rely that the methods you use returns the same results on any browser and is enough fast to use it.
为什么是 jQuery?一些本机属性如 window.outerHeight 在某些浏览器上实际上可以返回不准确的结果。jQuery 修复了这个问题,因此您可以信赖所使用的方法在任何浏览器上返回相同的结果并且足够快以使用它。
Here is a very simple way to achieve the infinite scroll without any performance impact:
这是实现无限滚动而不影响性能的一种非常简单的方法:
$(window).on('scroll', function() {
var threshold = 120;
if (window.pageYOffset > 0 && window.pageYOffset + $(window).outerHeight(false) >= $(document).outerHeight(false) - threshold) {
// call your infinite scroll callback, like infiniteScrollDebounced($('#mytable'))
}
}).scroll();
Notes: the condition in the if clause is intentionally like this, so if the user does not scroll, it will not calculate after window.pageYOffset > 0 and also get into the if (some micro-optimizations ;) ). The zero can be replaced with 20 or 100, so this is the threshold after the site will try to check if the user scrolls and need to do something about it.
注意:if 子句中的条件是故意这样的,所以如果用户不滚动,它不会在 window.pageYOffset > 0 之后计算,也会进入 if(一些微优化;))。零可以用 20 或 100 替换,因此这是站点将尝试检查用户是否滚动并需要对其做些什么之后的阈值。
I use debounce to postpone the real call to load data (usually websites load data when infinite scrolls), demo: https://davidwalsh.name/function-debounce
我使用 debounce 来推迟加载数据的真正调用(通常是网站在无限滚动时加载数据),演示:https: //davidwalsh.name/function-debounce
So I have this method:
所以我有这个方法:
var infiniteScrollDebounced = _.debounce(function($table) {
var params = $table.data('table-params');
// Don't request any more if we have reached the end
if (params.end)
return;
params.page++;
params.append = true;
GridHelper.reload($table, null, params);
}, 100, true);
My table have data attached to hold the current progress (page, sorting, filtering, etc) and this data is retrieved and passed into the query, so I get properly ordered and filtered results every time. GridHelper.reload() function handles the request and updates the params of the table when the data arrives (the new params are part of the response).
我的表附加了数据来保存当前进度(页面、排序、过滤等),并且这些数据被检索并传递到查询中,所以我每次都能得到正确排序和过滤的结果。GridHelper.reload() 函数处理请求并在数据到达时更新表的参数(新参数是响应的一部分)。