ahooks源码学习之useVirtualList
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相关推荐
- 我写了 ahooks 源码分析系列,收到官方邀请我一起维护,这是一次提 PR 的记录...
大家好,我是若川.持续组织了近一年的源码共读活动,感兴趣的可以 加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步.同时极力推荐订阅我写的<学习源码整体架构系列& ...
- Shiro源码学习之二
接上一篇 Shiro源码学习之一 3.subject.login 进入login public void login(AuthenticationToken token) throws Authent ...
- Shiro源码学习之一
一.最基本的使用 1.Maven依赖 <dependency><groupId>org.apache.shiro</groupId><artifactId&g ...
- mutations vuex 调用_Vuex源码学习(六)action和mutation如何被调用的(前置准备篇)...
前言 Vuex源码系列不知不觉已经到了第六篇.前置的五篇分别如下: 长篇连载:Vuex源码学习(一)功能梳理 长篇连载:Vuex源码学习(二)脉络梳理 作为一个Web前端,你知道Vuex的instal ...
- vue实例没有挂载到html上,vue 源码学习 - 实例挂载
前言 在学习vue源码之前需要先了解源码目录设计(了解各个模块的功能)丶Flow语法. src ├── compiler # 把模板解析成 ast 语法树,ast 语法树优化,代码生成等功能. ├── ...
- 2021-03-19Tomcat源码学习--WebAppClassLoader类加载机制
Tomcat源码学习--WebAppClassLoader类加载机制 在WebappClassLoaderBase中重写了ClassLoader的loadClass方法,在这个实现方法中我们可以一窥t ...
- jQuery源码学习之Callbacks
jQuery源码学习之Callbacks jQuery的ajax.deferred通过回调实现异步,其实现核心是Callbacks. 使用方法 使用首先要先新建一个实例对象.创建时可以传入参数flag ...
- JDK源码学习笔记——Integer
一.类定义 public final class Integer extends Number implements Comparable<Integer> 二.属性 private fi ...
- DotText源码学习——ASP.NET的工作机制
--本文是<项目驱动学习--DotText源码学习>系列的第一篇文章,在这之后会持续发表相关的文章. 概论 在阅读DotText源码之前,让我们首先了解一下ASP.NET的工作机制,可以使 ...
最新文章
- 教育学专硕考试科目计算机,2017考研:哪些专业的考试科目相同?
- 在进入新版本 的时候,进行推送引导
- 导入新的一个android项目抱错
- 什么样的计算机书才是市场需要的——2009年计算机图书选题策划方向(三) (全文完)...
- SQL语言之DQL语言学习(十)子查询
- Win10:tensorflow学习笔记(4)
- 玩转C语言之数组-数组指针
- JAVA 海啸_java线程总结
- JavaWeb完整项目要用到的专业技能
- 乙级(Basic Level) 1009 数字黑洞
- innosetup区分正常状态和静默安装状态(通过传递的参数)
- 密码学专题 证书和CA指令 申请证书|建立CA|CA操作|使用证书|验证证书
- java xpdf 转换成html_java将Word/Excel/PDF文件转换成HTML整理
- C/C++ 获取本地日期时间常见方法
- 数学建模算法与应用(一)线性规划
- Hspice学习资源和心得
- 其实,我对你是有一些失望的。
- 我的秋招经验分享(内附校招交流群)
- 用Python实现求整数各位上数字之和
- 分类:决策树——剪枝
热门文章
- 微信小程序实现双向数据绑定
- Android利用GridView加载九宫格菜单
- GPT-4推理提升1750%!普林斯顿清华姚班校友提出全新「思维树ToT」框架,让LLM反复思考...
- 给linux4.19内核打上补丁(支持RNDIS)
- Android 如果读取asserts 中的db文件,并进行查询操作
- 二合一平板如何摆脱“概念”炒作?
- 通过身份证号码判断是否已成年
- INSTANCE/HWND/CWnd/HANDLE区别
- Altium designer如何将制作一个自己的logo
- 知识改变命运,技术决定薪资