当前位置:主页 > 技术方案 >

padding简单模式

发布时间:2021-01-06 16:21   浏览次数:次   作者:admin
长列表绘制,无限下拉也是前端开发中的一个老生常谈的问题,本文将介绍一种简明,巧妙,有效的方法。不用多说,看看下面的图片,也许你能找到什么?
不知道您是否从上面的图表中注意到了什么,比如仅仅渲染了视觉区域的部分DOM,在滚动时仅仅更改了外层容器的padding?
前面的一点很好理解,我们考虑到了性能问题,因此不可能渲染长列表的所有列表元素(甚至无限下拉列表),而随后的一点则是本文中介绍的这个方案的核心!
没有关子,事先告诉你计划的要素有两个:
接口观察者。
页面编辑。
说出这些要素,或许你可以开始思考,看看你能否猜出具体的实现方案。
计划介绍。
接口观察者。
基础理念
对于任何时候来说,检测一个元素的视觉状态或两个元素的相对视觉状态并不容易。各种常规方案不仅复杂,而且性能代价高昂,例如需要侦听滚动事件,然后查询DOM,获得元素高度、位置,计算距离窗口高度等。
IntersectionObserver将解决这个问题。对于开发者来说,异步查询元素相对于其他元素或窗口位置的方式非常方便,从而消除了昂贵的DOM查询和样式读取开销。
相容。
大部分Safari的兼容性很差,需要12.2或更多的兼容性,不过还好,还有polyfill可以吃。
某些应用方案。
懒散加载页面的实现。
无限制下拉(本文的实现)。
监控部分广告元素的曝光情况,进行相关数据统计。
监视用户的滚动行为是否到达目标位置,以实现某些交互逻辑(例如当视频元素滚动到隐藏位置时,会暂停)。
页面删除方案的实现。
在对IntersectionObserver有了基本的了解后,接下来看看如何使用IntersectionObserver+padding实现无限下拉。
首先概述一下总体思路:
侦听是否有固定长度列表的首个元素进入窗口;
对当前页面中第一个渲染元素更新相应的序号;
按照以上序号,得到目标数据元素,将列表的内容重新渲染到相应的位置;
容器参数调整,模拟滚动实现。
core:使用父元素的padding来填充一个无限下拉中本来就存在的DOM元素,只保留在窗口区域中的一定数量DOM元素用于数据渲染。
监听一组固定长度的元素是否在窗口中出现?
//观察者创建。
bobserver=newIntersectionObserver(callback,options);
观察列表的第一个元素和最后一个元素。
observer.observe(this.firstItem);
This.observer.observe(this.lastItem);
重复代码
例如,在页面中渲染固定的20个list元素,我们使用IntersectionObserver对第一个和最后一个元素进行观察,当其中一个元素重新进入窗口时,callback函数将触发:
连接包=(entries)=>{
entries.forEach(entry)=>{
IF(entry.target.id=firstItemId){
当第一个元素进入窗口时//。
}elseif(entry.target.id=lastItemId){
最后一个元素出现在窗口中时//。
}
});
};
重复代码
更新当前页面渲染的第一个元素(firstIndex)对应的序号
举个例子,我们使用数组来维护那些需要在页面中渲染的数据。当不断请求新数据时,数组的长度会不断地增大,并且总会呈现出一定数量的元素,如20。然后:
首先,在数组中,元素的序数为0-19,即在这个时候,相应的firstIndex为0;
当序号为19(即前一步的lastItem)的元素进入视窗时,我们将向后渲染10个元素,也就是在这个时间firstIndex中渲染序号为10-29的元素;
三,下一次是,当序号为29的元素进入窗口时,继续向后渲染10个元素,也就是渲染序号20-39的元素,然后在这个时间firstIndex为20,如此类推…
我们对原始firstIndex进行了一个缓存。
Const{currentIndex}=this.domDataCache;
将整个容器中的一半元素作为每次渲染的增量使用//。
constincrement=Math.floor(this.listsize/2);
莱特菲尔斯Index;
IF(isScrollDown){
向下滚动时,//序号增加。
firstIndex=当前Index+事件;
}else{
上滚时,//序号减少。
firstIndex=currentIndex-increment;
}
重复代码
总的来说,更新firstIndex,就是要知道应该根据页面的滚动情况来获取、渲染下一步的数据。
根据以上序号,获得相应的数据元素,将列表重新渲染为新的内容。
配置函数=(firstIndex)=>{
offset=firstIndex,limit=10=>getData。
getDataDone=>newdataItems=>renderDOM。
};
重复代码
该部分的工作是根据firstIndex查询数据,然后在页面上渲染目标数据。
padding调整,模拟滚动实现。
现在我们已经实现了数据更新和DOM元素更新,那么对于无限下拉效果和滚动效果,我们应该如何实现呢?
想像一下,抛开所有事情,最简单、最直接、最粗鲁的方法无非是我们把多出10个新的数据元素后,把多出的10个新DOM元素塞进页面来渲染这些数据。
但是现在,与上面的简单模式相比,我们的模式是:这10个新的数据元素,我们用原来的DOM元素进行渲染,替换掉那些离开了窗口且看不见的数据元素;并且,我们使用padding填充来模拟实现,以进一步提高容器高度。
滚动下去。
padding的增量=每个item的高度x新数据项数。
constremPaddingsVal=itemHeight*(Math.floor(this.listSize/2));
IF(isScrollDown){
增加//paddingTop,填充顶部位置。
新古典主义建筑=currentPaddingTop+remPaddingsVal;
(currentPaddingBottom===0){
新库伦帕丁堡堡=0;
}else{
如果初始值为paddingBottom,则减去该值,其中包含滚动到底部的元素。