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. 教育学专硕考试科目计算机,2017考研:哪些专业的考试科目相同?
  2. 在进入新版本 的时候,进行推送引导
  3. 导入新的一个android项目抱错
  4. 什么样的计算机书才是市场需要的——2009年计算机图书选题策划方向(三) (全文完)...
  5. SQL语言之DQL语言学习(十)子查询
  6. Win10:tensorflow学习笔记(4)
  7. 玩转C语言之数组-数组指针
  8. JAVA 海啸_java线程总结
  9. JavaWeb完整项目要用到的专业技能
  10. 乙级(Basic Level) 1009 数字黑洞
  11. innosetup区分正常状态和静默安装状态(通过传递的参数)
  12. 密码学专题 证书和CA指令 申请证书|建立CA|CA操作|使用证书|验证证书
  13. java xpdf 转换成html_java将Word/Excel/PDF文件转换成HTML整理
  14. C/C++ 获取本地日期时间常见方法
  15. 数学建模算法与应用(一)线性规划
  16. Hspice学习资源和心得
  17. 其实,我对你是有一些失望的。
  18. 我的秋招经验分享(内附校招交流群)
  19. 用Python实现求整数各位上数字之和
  20. 分类:决策树——剪枝

热门文章

  1. 微信小程序实现双向数据绑定
  2. Android利用GridView加载九宫格菜单
  3. GPT-4推理提升1750%!普林斯顿清华姚班校友提出全新「思维树ToT」框架,让LLM反复思考...
  4. 给linux4.19内核打上补丁(支持RNDIS)
  5. Android 如果读取asserts 中的db文件,并进行查询操作
  6. 二合一平板如何摆脱“概念”炒作?
  7. 通过身份证号码判断是否已成年
  8. INSTANCE/HWND/CWnd/HANDLE区别
  9. Altium designer如何将制作一个自己的logo
  10. 知识改变命运,技术决定薪资