useVirtualList用于虚拟化列表,用于解决展示海量数据渲染时首屏渲染缓慢和滚动卡顿的问题。

总体实现思路:从start到end处截取数据的一部分,监听scroll事件,实时改变start和end

首先做一些前置工作,计算需要用到的变量。

第一步:计算container的容量(viewCapacity)。如果props中的itemHeight是以像素为单位的数字,则容量为container的高度除itemHeight。如果props的itemHeight是动态值,则for循环列表数据累加itemHeight,得到container容量。

if (typeof itemHeight === 'number') {return Math.ceil(containerHeight / itemHeight);
}for (var i = start; i < list.length; i++) {var height = itemHeight(i);sum += height;if (sum >= containerHeight) {capacity = i;break;}}
return capacity - start;

第二步:计算列表数据对于container的偏移数量(offset)。做法为scrollTop / itemHeight。

if (typeof itemHeight === 'number') {return Math.floor(scrollTop / itemHeight) + 1;
}for (var i = 0; i < list.length; i++) {var height = itemHeight(i);sum += height;if (sum >= scrollTop) {offset = i;break;}}return offset + 1;

第三步:计算在container区域内可显示的数据个数(calculateRange)。start: offset - overscan;end: offset + viewCapacity + overscan。overscan为可允许溢出container范围的最大个数。同时setState({start, end})

    if (element) {var offset = getOffset(element.scrollTop);var viewCapacity = getViewCapacity(element.clientHeight);var from = offset - overscan;var to = offset + viewCapacity + overscan;setState({start: from < 0 ? 0 : from,end: to > list.length ? list.length : to});}

第四步:计算wrapper的高度。

  var totalHeight = react_1.useMemo(function () {if (typeof itemHeight === 'number') {return list.length * itemHeight;}return list.reduce(function (sum, _, index) {return sum + itemHeight(index);}, 0);}, [list.length]);

第五步:计算列表距container的高度(distanceTop)。监听state中的start,重新计算该值。

    if (typeof itemHeight === 'number') {var height_1 = index * itemHeight; // if (enableCache) {return height_1;}var height = list.slice(0, index).reduce(function (sum, _, i) {return sum + itemHeight(i);}, 0); 

总结:监听container的Scroll事件,当滚动时,计算在container区域可显示的数据个数,同时修改列表可显示的范围(start和end)。之后计算当前已滚动的高度(distanceTop)。最后修改wrapper的marginTop。

源码地址:https://github.com/alibaba/hooks/blob/master/packages/hooks/src/useVirtualList/index.ts

最后:useVirtualList还利用resize-observer-polyfill监听了container的size,同时重新计算了calculateRange。

ahooks源码学习之useVirtualList相关推荐

  1. 我写了 ahooks 源码分析系列,收到官方邀请我一起维护,这是一次提 PR 的记录...

    大家好,我是若川.持续组织了近一年的源码共读活动,感兴趣的可以 加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步.同时极力推荐订阅我写的<学习源码整体架构系列& ...

  2. Shiro源码学习之二

    接上一篇 Shiro源码学习之一 3.subject.login 进入login public void login(AuthenticationToken token) throws Authent ...

  3. Shiro源码学习之一

    一.最基本的使用 1.Maven依赖 <dependency><groupId>org.apache.shiro</groupId><artifactId&g ...

  4. mutations vuex 调用_Vuex源码学习(六)action和mutation如何被调用的(前置准备篇)...

    前言 Vuex源码系列不知不觉已经到了第六篇.前置的五篇分别如下: 长篇连载:Vuex源码学习(一)功能梳理 长篇连载:Vuex源码学习(二)脉络梳理 作为一个Web前端,你知道Vuex的instal ...

  5. vue实例没有挂载到html上,vue 源码学习 - 实例挂载

    前言 在学习vue源码之前需要先了解源码目录设计(了解各个模块的功能)丶Flow语法. src ├── compiler # 把模板解析成 ast 语法树,ast 语法树优化,代码生成等功能. ├── ...

  6. 2021-03-19Tomcat源码学习--WebAppClassLoader类加载机制

    Tomcat源码学习--WebAppClassLoader类加载机制 在WebappClassLoaderBase中重写了ClassLoader的loadClass方法,在这个实现方法中我们可以一窥t ...

  7. jQuery源码学习之Callbacks

    jQuery源码学习之Callbacks jQuery的ajax.deferred通过回调实现异步,其实现核心是Callbacks. 使用方法 使用首先要先新建一个实例对象.创建时可以传入参数flag ...

  8. JDK源码学习笔记——Integer

    一.类定义 public final class Integer extends Number implements Comparable<Integer> 二.属性 private fi ...

  9. DotText源码学习——ASP.NET的工作机制

    --本文是<项目驱动学习--DotText源码学习>系列的第一篇文章,在这之后会持续发表相关的文章. 概论 在阅读DotText源码之前,让我们首先了解一下ASP.NET的工作机制,可以使 ...

最新文章

  1. SAP S/4HANA BP功能
  2. 深入理解CSS盒模型
  3. MySQL存储引擎--------Federated最佳实战
  4. TensorFlow版本
  5. IP地址,子网掩码、默认网关,DNS服务器是什么意思
  6. 将FORMSTYLE类型由FSNORMAL变为FSMDICHILD时,窗体的VISIBLE自动设为TRUE.且create之后,自动运行onshow事件。
  7. 转]一个计算机专业学生几年的Java编程经验汇总
  8. boost::math::inverse_gamma_distribution用法的测试程序
  9. C++ 高级篇(一)—— 模板(Templates)
  10. 最新版Spring Cloud Alibaba微服务架构-Ribbon负载均衡篇
  11. FileItem类的常用方法
  12. 常用numpy模块用法总结
  13. 第四周 项目中的白盒测试
  14. TakeColor鼠标位置不对/取色不准
  15. 绝对纯净:龙行天下GHOST XP SP3软件自选安装纯净版 2010 V13.0 2010年6月
  16. Android 购物选择颜色、尺码实现
  17. esp32测试wifi速率
  18. 赛尔号无限宇宙服务器,赛尔号无限宇宙
  19. 数据挖掘流程总结及案例分析
  20. 单峰数组求第k大算法

热门文章

  1. fineui mysql_FineUI从iis6迁移到iis7.5上遇到的奇葩事情
  2. 图解CyclicBarrier运动员接力赛
  3. CS5801AN是一个HDMI2.0b到DP1.4a转换器
  4. Windows系统升级node.js版本
  5. DOTA2地形纹理贴图整理
  6. C# 9 对IEnumerator类似物应用foreach
  7. p5.js 2.0绘制一幅动态图像
  8. element中树形数据与懒加载实现全部展开和全部收起
  9. 计算机没有usb视频教程,USB连接电脑没反应【图文教程】
  10. linux捕获鼠标点击事件文件,linux获得键盘鼠标事件,模拟键盘鼠标按键