当前位置:首页 »“秋了秋”个人博客 » 前端编程 » 不定高度虚拟滚动实现方案

不定高度虚拟滚动实现方案

作者:秋了秋 发表时间:2023年12月09日

Web前端界的虚拟滚动方案都是假设所有行高一样,通过计算屏幕可视高度计算出科容纳有多少行数据从而插入多少行dom,至于滚动条是计算所有行需要的高度然后用padding撑起来。这种虚拟滚动有一个缺陷就是必须是单行,或者每行数据高度一致,不允许任意换行,如何解决这个痛点?以下是我研究的实现方案,可参考。

复制代码
  1. <div style="height:400px;width:800px;overflow: auto;border: 1px solid #ccc" id="scroller"><div id="container" ></div></div>
  2. <script type="text/javascript">
  3. // 模拟高度不等的一万条数据
  4. let dataArray = [], beginIndex = 0, segIndex = 0, beginSetHeight, lastBeginIndex, lastType;
  5. for(let i = 0; i < 10000; i++) {
  6. dataArray.push(+ '. ' + new Array(Math.ceil(Math.random() * 10)).fill('数据数据数据数据数据数据数据数据'));
  7. }
  8. let minCount = parseInt(parseInt(scroller.style.height) / 16); // 假设最小行高为16像素(一行字体的高度)
  9.  
  10. // 初始化往容器填充维持滚动的最小量数据
  11. addContent('append');
  12.  
  13. const scrollHeight = parseInt(scroller.style.height);
  14. let scrollTimer;
  15. scroller.onscroll = (e)=>{
  16. if(scrollTimer || beginSetHeight) {
  17. return; //beginSetHeight 禁止因设置高度触发onscroll
  18. }
  19. scrollTimer = setTimeout(function() {
  20. // 视窗高度
  21. var containerHeight = parseFloat(container.offsetHeight);
  22. // 滚动条位置
  23. var scrollTop = scroller.scrollTop;
  24. if (scrollTop + scrollHeight >= containerHeight) {
  25. console.log('滚动到达底部');
  26. addContent('append');
  27. } else if(scrollTop <= 0) {
  28. console.log('滚动到达顶部');
  29. addContent('prepend');
  30. }
  31. clearTimeout(scrollTimer);
  32. scrollTimer = null;
  33. }, 100)
  34. }
  35. function solveIndex() {
  36. // index临界处理
  37. if(beginIndex <= 0) {
  38. beginIndex = 0;
  39. }
  40. if(beginIndex + minCount >= dataArray.length - 1) {
  41. beginIndex = dataArray.length - 1 - minCount;
  42. }
  43. }
  44. function addContent(type) {
  45. const seg = document.createElement('div');
  46. seg.className = 'seg seg' + segIndex++;
  47. if(lastBeginIndex === beginIndex && lastType === type) {
  48. return;
  49. }
  50. beginSetHeight = true;
  51. // lastType !== type 反向滚动
  52. if(lastType !== type && lastType) {
  53. if(type === 'append') {
  54. beginIndex += minCount * 3;
  55. } else {
  56. beginIndex -= minCount * 3;
  57. }
  58. solveIndex();
  59. }
  60. for (let i = beginIndex; i < beginIndex + minCount; i++) {
  61. const p = document.createElement('p');
  62. p.innerHTML = dataArray[i];
  63. seg.appendChild(p);
  64. }
  65. if(type === 'append') {
  66. container.appendChild(seg);
  67. } else {
  68. container.insertBefore(seg, document.querySelector('.seg'));
  69. scroller.scrollTop = seg.offsetHeight;
  70. }
  71. lastBeginIndex = beginIndex;
  72. lastType = type;
  73. // 清理上上一个seg,页面始终只保留两个有内容的seg
  74. const segs = container.querySelectorAll('.seg');
  75. if(segs.length > 2) {
  76. const removeSeg = type === 'append' ? segs[0] : segs[segs.length - 1];
  77. const originScrollTop = scroller.scrollTop, height = removeSeg.offsetHeight;
  78. container.removeChild(removeSeg);
  79. scroller.scrollTop = type === 'append' ? originScrollTop - height : originScrollTop;
  80. }
  81. if(type === 'append') {
  82. beginIndex += minCount;
  83. } else {
  84. beginIndex -= minCount;
  85. }
  86. solveIndex();
  87. setTimeout(function() {
  88. beginSetHeight = false; //禁止因设置高度和代码设置scrollTop触发onscroll
  89. }, 100)
  90. }
  91. </script>
复制代码

直接复制代码放到html页面里面的body标签内即可看到效果

0. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

1. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

2. 数据数据数据数据数据数据数据数据

3. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

4. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

5. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

6. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

7. 数据数据数据数据数据数据数据数据

8. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

9. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

10. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

11. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

12. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

13. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

14. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

15. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

16. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

17. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

18. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

19. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

20. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

21. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

22. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

23. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据

24. 数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据,数据数据数据数据数据数据数据数据



0
文章作者: “秋了秋”个人博客,本站鼓励原创。
转载请注明本文地址:http://netblog.cn/blog/506.html
目录: 前端编程标签: 虚拟滚动 1210次阅读

检测到你在使用低版本浏览器不支持自动播放,请手动点击播放,将为你使用特制播放源播放。

请求播放音乐,请点击播放

登 录
点击获取验证码
还没账号?点击这里