在本教程中,我们将看到一个使用无限滚动方法分解页面内容的简单实现。我们将使用HTML、CSS和vanillaJavaScript来构建无限滚动功能的高性能且可访问的版本。什么是无限滚动? 无限滚动是一种用于在用户滚动到页面末尾时在页面上动态加载更多内容的功能。 无限滚动的概念用于以一种用户感觉无缝的方式从服务器加载数据,但不会因为一次请求太多数据而使服务器过载。 在之前的教程中,我们实现了分页功能,它允许我们将内容分解为称为页面的可导航部分。本教程将使用类似的实现。原生JavaScript的好处 使用JavaScript的一个显着好处是我们的实现与框架无关,即它不依赖于任何框架,因此可以对其进行修改以在所有框架上工作。 此外,由于我们自己构建功能而不依赖于插件,因此我们可以确保实现是轻量级的并且完全适合我们的需求。 这是最终产品的外观,滚动到笔的底部以加载更多内容:1。用HTML标记 我们将从在页面上放置卡片的容器开始。我们将使用JavaScript将卡片添加到容器中,因此p将为空。 我们还有一个加载器p,用于在添加下一批卡片之前显示动画,以及p用于显示卡片数量和卡片总数的卡片操作。 Showing of cards span 加载器和卡片计数p的外观2。使用CSS进行样式设置 我们将添加到cardcontainerp中的卡片将有一个类名card。 cardcontainer{ display:flex; flexwrap:wrap; } 。card{ height:55vh; width:calc((1003)16px); margin:8px; borderradius:3px; transition:all200mseaseinout; display:flex; alignitems:center; justifycontent:center; } 。card:hover{ boxshadow:04px10pxrgba(0,0,0,0。2); } 。cardactions{ margin:8px; padding:16px0; display:flex; justifycontent:spacebetween; alignitems:center; } 我们还将通过动画::after伪选择器为加载器p中的骨架卡创建加载动画: loader{ display:flex; } 。skeletoncard{ height:55vh; width:calc((1003)16px); margin:8px; borderradius:3px; transition:all200mseaseinout; position:relative; backgroundcolor:eaeaea; } 。skeletoncard::after{ content:; position:absolute; top:0; right:0; bottom:0; left:0; transform:translateX(100); backgroundimage:lineargradient(90deg,rgba(255,255,255,0)0,rgba(255,255,255,0。2)20,rgba(255,255,255,0。5)60,rgba(255,255,255,0)); animation:load1sinfinite; } keyframesload{ 100{ transform:translateX(100); } } 无障碍样式 每当我们在网页上包含动画时,重要的是要考虑可访问性的影响。有些用户可能更喜欢根本没有动画,我们可以通过使用媒体规则在样式中考虑这种偏好,prefersreducedmotion mediascreenand(prefersreducedmotion:reduce){ 。skeletoncard::after{ animation:none; } } 3。JavaScript的功能 让我们分解无限滚动背后的逻辑。定义要在页面上加载的内容的限制。检测用户何时到达内容容器的末尾。到达容器末尾后加载更多内容。如果没有更多内容要加载,请停止无限滚动。定义常量 首先,让我们从DOM中获取我们需要的所有元素: constcardContainerdocument。getElementById(cardcontainer); constcardCountElemdocument。getElementById(cardcount); constcardTotalElemdocument。getElementById(cardtotal); constloaderdocument。getElementById(loader); 现在我们需要定义我们的全局变量。 我们需要一个要添加到页面的最大卡片数量的值。如果您从服务器获取数据,则此值是服务器响应的长度。让我们初始化一个99的卡片限制。 constcardLimit99; cardTotalElem是用于在页面上显示最大卡片数量的元素,因此我们可以将设置为innerHTML值cardLimit; cardTotalElem。innerHTMLcardLimit; 然后我们将定义一个变量来表示要增加页面的卡片数量: constcardIncrease9; 我们想知道我们将拥有多少页面,即我们可以增加多少次内容,直到达到最大限制。例如,使用我们定义的cardLimit和cardIncrease变量,我们可以将内容增加10倍(假设我们已经加载了前9个元素),直到达到限制。我们将通过除以来做到这cardLimit一点cardIncrease。 constpageCountMath。ceil(cardLimitcardIncrease); 然后我们将定义一个值来确定我们在哪个页面上: letcurrentPage1; 创建新卡 现在我们有了所有的常量,让我们创建一个函数来向卡片容器中添加一张新卡片。我们将innerHTML卡片的设置为索引值,这样我们就可以跟踪我们正在添加的卡片数量。 此演示中的一个有趣功能是每张卡片都有随机生成的背景颜色。如何使用JavaScript生成随机背景颜色 constgetRandomColor(){ consthMath。floor(Math。random()360); returnhsl({h}deg,90,85); }; constcreateCard(index){ constcarddocument。createElement(p); card。classNamecard; card。innerHTMLindex; card。style。backgroundColorgetRandomColor(); cardContainer。appendChild(card); }; 将卡片添加到容器中 现在我们将使用与分页教程类似的功能将卡片添加到容器中。 首先,确定要添加到页面的卡片范围。该addCards函数将接受一个pageIndex参数,该参数将更新全局currentPage值。如果我们在第1页,我们将添加卡片1到9。如果我们在第2页,我们将添加卡片10到18,依此类推。 我们可以在数学上将其定义为: constaddCards(pageIndex){ currentPagepageIndex; conststartRange(pageIndex1)cardIncrease; constendRangepageIndexcardIncrease; for(letistartRange1;icurrRange;i){ createCard(i); } }; 在这个函数中,我们的开始范围总是比我们试图获得的值小一(即在第1页,开始范围是0,在第2页,开始范围是9)所以我们将考虑这一点通过将我们的for循环索引的值设置为startRange1。检测何时达到卡限制 我们必须注意的一个限制是endRange数量。如果我们在最后一页,我们希望结束范围与cardLimit。例如,如果我们有cardLimit75和cardIncrease10的a并且我们在第8页,我们的起始索引将是70,我们的endRange值应该是75。 我们将修改我们的addCards函数来解决这个问题: constaddCards(pageIndex){ currentPagepageIndex; conststartRange(pageIndex1)cardIncrease; constendRangecurrentPagepageCount?cardLimit:pageIndexcardIncrease; for(letistartRange1;iendRange;i){ createCard(i); } }; 我们的演示还包括一个cardTotal元素,该元素显示页面上当前显示的卡片数量,因此我们innerHTML将此元素的设置为结束范围。 constaddCards(pageIndex){ currentPagepageIndex; conststartRange(pageIndex1)cardIncrease; constendRangecurrentPagepageCount?cardLimit:pageIndexcardIncrease; cardCountElem。innerHTMLendRange; for(letistartRange1;iendRange;i){ createCard(i); } }; 加载初始卡片 我们已经定义了将卡片添加到容器的功能,因此我们将包含一个window。onload函数来设置要添加到页面的初始卡片。 window。onloadfunction(){ addCards(currentPage); }; 处理无限滚动 currentPage当我们到达页面末尾时,我们将通过增加向容器添加新卡片的数量来处理无限滚动。innerHeight我们可以通过将窗口的值添加到滚动值pageYOffset并将其与offsetHeight作为页面总高度的文档进行比较来检测何时到达页面末尾。 这是它的外观的视觉表示: 一旦我们到达页面的末尾,我们想通过调用addCardscurrentPage1的函数来加载一个新页面。 consthandleInfiniteScroll(){ constendOfPagewindow。innerHeightwindow。pageYOffsetdocument。body。offsetHeight; if(endOfPage){ addCards(currentPage1); } }; 然后我们为窗口滚动创建一个事件监听器,并将上面的函数传递给它: window。addEventListener(scroll,handleInfiniteScroll); 性能优化 由于我们正在使用滚动事件侦听器,因此限制调用次数对我们网页的性能是有益的。我们可以使用节流功能减慢调用次数。如何使用JavaScript实现Debounce和Throttle杰迈玛阿布2021年5月3日 我们将这样定义我们的节流函数: varthrottleTimer; constthrottle(callback,time){ if(throttleTimer)return; throttleTimertrue; setTimeout((){ callback(); throttleTimerfalse; },time); }; 然后我们将油门函数传递给handleInfiniteScroll函数 consthandleInfiniteScroll(){ throttle((){ constendOfPage window。innerHeightwindow。pageYOffsetdocument。body。offsetHeight; if(endOfPage){ addCards(currentPage1); } },1000); }; 停止无限滚动 至此,我们已经设置了函数,以便在到达页面末尾时添加更多内容。现在,让我们确保我们的函数在没有要添加的内容时停止运行,即cardLimit到达时。 首先,让我们定义我们的removeInfiniteScroll函数。在此函数中,我们将从handleInfiniteScroll滚动事件侦听器中删除该函数,并删除加载器p。 constremoveInfiniteScroll(){ loader。remove(); window。removeEventListener(scroll,handleInfiniteScroll); }; 现在我们将修改我们handleInfiniteScroll以考虑是否没有更多内容要添加,即我们在内容的最后一页。 consthandleInfiniteScroll(){ throttle((){ constendOfPage window。innerHeightwindow。pageYOffsetdocument。body。offsetHeight; if(endOfPage){ addCards(currentPage1); } if(currentPagepageCount){ removeInfiniteScroll(); } },1000); }; 结论 我们终于得到它了!我们已经构建了无限滚动功能的高性能且可访问的实现。