当前位置: 首页 > news >正文

antd4里table的滚动是如何实现的?

在这里插入图片描述

rc-table里Header、Footer、TableBody实现保持同频滚动的方法

场景:Header、Footer都有,Table设置了scrollX,才关注同频滚动

那么是如何实现的?

  1. 监听onScroll方法获取到滚动条向左的滚动的距离scrollLeft;
  2. 同时给三个dom设置scrollLeft

rc-table里的onScroll实现

先看一般的onScroll实现

  1. 监听onScroll获取scrollLeft
  2. 设置header、footer、tableBody的scrollLeft
    下面是伪代码哈
const onScroll = (e: ScrollEvent) => {// 拿到scrollLeftconst scrollLeft = e.target.scrollLeft// 给所有的header、footer、table-body设置scrollLeftheader.scrollLeft = scrollLeftfooter.scrollLeft = scrollLefttableBody.scrollLeft = scrollLeft
}

源码里onScroll的实现

 const onScroll = ({currentTarget,scrollLeft,}: {currentTarget: HTMLElement;scrollLeft?: number;}) => {const mergedScrollLeft = typeof scrollLeft === 'number' ? scrollLeft : currentTarget.scrollLeft;const compareTarget = currentTarget || EMPTY_SCROLL_TARGET; if (!getScrollTarget() || getScrollTarget() === compareTarget) { setScrollTarget(compareTarget);//一个 滚动需要 控制 header、body、summary、stickyScrollBar所有同步滚动// header设置scrollLeftscrollHeaderRef.current = mergedScrollLeft// body 设置scrollLeftscrollBodyRef.current = mergedScrollLeft}};

对比两个的实现,可以看到rc-table里的实现多了一个入参scrollLeft和一个if判断;
为什么多了一个入参、一个判断?继续往下看?

Header、Footer的滚动监听

  1. 用组件FixedHolder实现,给FixedHolder绑定ref;
  2. 监听的是onWheel, 不是onScroll;
    为什么监听onWheel不是onScroll?
React.useEffect(() => {function onWheel(e: WheelEvent) {// deltaX: Returns a double representing the horizontal scroll amountconst { currentTarget, deltaX } = e as unknown as React.WheelEvent<HTMLDivElement>;// 避免触发不必要滚动, 是一种优化if (deltaX) {onScroll({ currentTarget, scrollLeft: currentTarget.scrollLeft + deltaX });e.preventDefault();}}fixHolder.current?.addEventListener('wheel', onWheel);return () => {fixHolder.current?.removeEventListener('wheel', onWheel);};}, []);

不要将 onscroll 与 onwheel混淆。onwheel 是鼠标滚轮旋转,而 onscroll 处理的是对象内部内容区的滚动事件。
当dom满足下面任意一条的时候,不会触发onScroll;

  1. overflow:hidden
  2. 滚动条不存在

FixHolder组件

设置了样式overflow:hidden;

<divstyle={{overflow: 'hidden',...(isSticky ? { top: stickyTopOffset, bottom: stickyBottomOffset } : {}),}}ref={setScrollRef}className={classNames(className, {[stickyClassName]: !!stickyClassName,})}/><tablestyle={{tableLayout: 'fixed',visibility: noData || mergedColumnWidth ? null : 'hidden',}}>{(!noData || !maxContentScroll || allFlattenColumnsWithWidth) && (<ColGroupcolWidths={mergedColumnWidth ? [...mergedColumnWidth, combinationScrollBarSize] : []}columCount={columCount + 1}columns={flattenColumnsWithScrollbar}/>)}{children({...props,stickyOffsets: headerStickyOffsets,columns: columnsWithScrollbar,flattenColumns: flattenColumnsWithScrollbar,})}</table></div>

通过ref,调用useCallback赋值dom;利用scrollRef.current监听wheel事件,转成onScroll,增加入参scrollLeft;

const setScrollRef = React.useCallback((element: HTMLElement) => {scrollRef.current = element;}, []);

TableBody的滚动

当然是监听onScroll事件;
给Tables设置scrollX的情况下,TableBody设置样式{overflow-x: auto}这样会有同频滚动

<divstyle={...scrollXStyle,...scrollYStyle}onScroll={onScroll}ref={scrollBodyRef}><TableComponent>{bodyColGroup}{bodyTable}</TableComponent></div>

获得当前正在执行的dom

const [setScrollTarget, getScrollTarget] = useTimeoutLock(null);

getScrollTarget用来获得当前正在执行的dom
使用useState来存储正在执行的dom; 当组件重新渲染,dom更新,此时正在执行的dom,在下一个render的时候,就变了;useRef在下一次渲染之前不重新赋值,还是保留和上一次一样的值;
源码里使用useRef + setTimeout实现;useRef是用来存放当前正在执行的dom;setTimeout用来节流;
其中getState获取正在执行当前state,可能是空的;setState设置当前的State,并且在100ms以后清空设置的状态;

export function useTimeoutLock<State>(defaultState?: State): [(state: State) => void, () => State | null] {const frameRef = useRef<State | null>(defaultState || null);const timeoutRef = useRef<number>();function cleanUp() {window.clearTimeout(timeoutRef.current);}function setState(newState: State) {frameRef.current = newState;// 清空上一次的定时器cleanUp();timeoutRef.current = window.setTimeout(() => {frameRef.current = null;timeoutRef.current = undefined;}, 100);}function getState() {return frameRef.current;}useEffect(() => cleanUp, []);return [setState, getState];
}

onScroll为什么设置if判断

getScrollTarget()调用onScroll的之前,是否有滚动的dom; 没有就更新;有,判断是否和触发onScroll是相同Dom;是,更新;目的是为了避免执行上一个onScroll的时候,下一个onScroll执行,陷入循环,就相当于节流了;hooks版本的节流

const compareTarget = currentTarget || EMPTY_SCROLL_TARGET; 
// 固定滚动项
// 在处理上一个滚动的时候,禁止下一个也滚动执行onScroll
if (!getScrollTarget() || getScrollTarget() === compareTarget) {setScrollTarget(compareTarget);
}

看这块逻辑的时候,优化细节👍;从hooks的角度,实现节流;wheel和scroll都是滚动,但是也有区别;并且在react里支持dom绑定onScroll、onWheel;

rc-table如何固定左右两侧

场景:table的columns里设置fixed属性的时候,会出现滚动;fixed:true | 'left'固定左侧;fixed: 'right'固定右侧;

  1. 获取columns、columnWidths, 更新每个column的sticky的偏移距离;
  2. 更新涉及到fixed相关属性,fixedLeft、fixedRight、lastFixLeft、firstFixRight、lastFixRight、firstFixLeft、isSticky

相关链接:
rc-table: https://github.com/react-component/table
antd-table: https://ant.design/components/table-cn#components-table-demo-fixed-columns

相关文章:

antd4里table的滚动是如何实现的?

rc-table里Header、Footer、TableBody实现保持同频滚动的方法 场景&#xff1a;Header、Footer都有&#xff0c;Table设置了scrollX&#xff0c;才关注同频滚动 那么是如何实现的&#xff1f; 监听onScroll方法获取到滚动条向左的滚动的距离scrollLeft&#xff1b;同时给三个…...

抓取namenode 50070 jmx的指标信息

在生产实践过程中&#xff0c;需要把data退役之后需要停机下线&#xff0c;在下线之前需要确认机器是否已下线完成&#xff0c;要去namenode的50070界面上查看显然效率低&#xff0c;为了能够快速拿到节点信息&#xff0c;写了简单的脚本。jmx/50070还有很多信息可以获取&#…...

aspnetcore-browser-refresh.js和Visual Studio Browser Link

我在调试ASP.NET Core web应用时&#xff0c;发现请求的页面文档底部多了一部分文件&#xff0c;而在我的页面中却没有包含&#xff0c;故查询资料&#xff0c;在此记录&#xff1a; 图中&#xff0c;可以看到红框部分是多出来了2个脚本 1.aspnetcore-browser-refresh.js 这里…...

hadoop 集群常用命令(学习笔记) —— 筑梦之路

概念介绍 #HDFS 概述Hadoop Distributed File System&#xff0c;简称HDFS&#xff0c;是一个分布式文件系统。&#xff08;1&#xff09;NameNode&#xff08;nn&#xff09;&#xff1a;存储文件的元数据&#xff0c;如文件名&#xff0c;文件目录结构&#xff0c;文件属性&…...

ARC142D Deterministic Placing

ARC142D Deterministic Placing 题目大意 有一棵nnn个顶点的树&#xff0c;每个点上最多放一张卡片&#xff0c;你可以做如下操作&#xff1a; 同时将所有的卡片移到它所在顶点的相邻的一个顶点上 一个操作我们说它是好的&#xff0c;当下列条件满足&#xff1a; 每条边最…...

阶段八:服务框架高级(第二章:分布式事务)

阶段八&#xff1a;服务框架高级&#xff08;第二章&#xff1a;分布式事务&#xff09;Day-分布式事务0.学习目标1.分布式事务问题1.1.本地事务1.2.分布式事务1.3.演示分布式事务问题2.理论基础2.1.CAP定理2.1.1.一致性2.1.2.可用性2.1.3.分区容错2.1.4.矛盾2.2.BASE理论2.3.解…...

RPC异步化原理

深入RPC&#xff0c;更好使用RPC&#xff0c;须从RPC框架整体性能考虑问题。得知道如何提升RPC框架的性能、稳定性、安全性、吞吐量及如何在分布式下快速定位问题。RPC框架如何压榨单机吞吐量&#xff1f; 1 前言 TPS一直上不去&#xff0c;压测时CPU压到40%&#xff5e;50%就…...

C# 多窗口切换的实现

1、目的在主窗口中根据不同的按钮选择不同的子窗口显示。2、实现&#xff08;1&#xff09;、创建Winform窗体程序&#xff0c;放入SplitContainer控件splitContainer1将窗体分成左右2部分&#xff1b;&#xff08;2&#xff09;、在左侧splitContainer1.panel1中放入3个Button…...

【深度学习】RNN

1. 什么是RNN 循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;是一类以序列&#xff08;sequence&#xff09;数据为输入&#xff0c;在序列的演进方向进行递归&#xff08;recursion&#xff09;且所有节点&#xff08;循环单元&#xff09;按链式连接的递…...

招聘岗位,机会难得

岗位需求 费话不多说&#xff0c;直接上JD&#xff1a; 嵌入式开发工程师&#xff1a; 17:411.计算机、通信等相关专业。 2.熟悉网络基础知识&#xff0c;熟悉802.11a/b/g/n/ac协议&#xff0c;能通过抓包等分析手段排查定位各种wifi相关问题。 3.熟悉路由器主要功能及实现原…...

web打印的几种方法(2023)

在工作中出现web打印的情况是非常多的&#xff0c;其实这也是一个比较烦人的问题&#xff0c;这篇博客整理一下关于Web打印的一些方法或者方式。 1. window.print() 这个方法是用来打印网页的&#xff0c;页面上的其他的元素也会被打印处理&#xff0c;在打印的时候页眉页脚是…...

代码随想录算法训练营day44 | 动态规划之完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ

day44完全背包基础知识问题描述举个栗子518. 零钱兑换 II1.确定dp数组以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp数组377. 组合总和 Ⅳ1.确定dp数组以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例来推导dp数组完全背包基…...

IntelliJ IDEA 实用插件推荐(包含使用教程)

IntelliJ IDEA 实用插件推荐 背景&#xff1a;电脑重装了&#xff0c;重新下载了最新版的IntelliJ IDEA&#xff0c;感觉默认模式有点枯燥&#xff0c;于是决定从网上下载一些实用美观的插件优化自己以后吃饭的工具&#xff0c;现在推荐的都是目前还能用的&#xff08;亲身实践…...

WideDeep模型

google提出的Wide&deep模型&#xff0c;将线性模型与DNN很好的结合起来&#xff0c;在提高模型泛化能力的同时&#xff0c;兼顾模型的记忆性。wide&deep这种将线性模型与DNN的并行连接模式&#xff0c;后来称为推荐领域的经典模式&#xff0c;奠定了后面深度学习模型的…...

nacos集群模式+keepalived搭建高可用服务

实际工作中如果nacos这样的核心服务停掉了或者整个服务器宕机了&#xff0c;那整个系统也就gg了&#xff0c;所以像这样的核心服务我们必须要搞个3个或者3个以上的nacos集群部署&#xff0c;实现高可用&#xff1b; 部署高可用版本之前&#xff0c;首先你要会部署单机版的naco…...

吉利「银河」负重突围

吉利控股集团最新公布的数据显示&#xff0c;2022年&#xff0c;吉利控股集团汽车总销量超230万辆&#xff0c;同比增长4.3%。其中&#xff0c;新能源汽车销量超64万辆&#xff0c;同比增长100.3%。 在中国本土市场&#xff0c;2022年吉利集团旗下品牌乘用车总交付量为135.84万…...

QT之图形视图框架概述——Graphics View Framework

QT之图形视图框架概述——Graphics View Framework1. 概述2. 核心类3. 事件传递4. Graphics View 坐标系统5. 参考1. 概述 Graphics View Framework是子Qt 4.2引入的&#xff0c;用来取代之前版本中的QCanvas。Graphics View Framework提拱了用于大量2D图形项的管理和交互的能…...

【SQL开发实战技巧】系列(二十二):数仓报表场景(上) 从分析函数效率一定快吗聊一聊结果集分页和隔行抽样实现方式

系列文章目录 【SQL开发实战技巧】系列&#xff08;一&#xff09;:关于SQL不得不说的那些事 【SQL开发实战技巧】系列&#xff08;二&#xff09;&#xff1a;简单单表查询 【SQL开发实战技巧】系列&#xff08;三&#xff09;&#xff1a;SQL排序的那些事 【SQL开发实战技巧…...

小米无线AR眼镜探索版细节汇总

在MWC 2023期间&#xff0c;小米正式发布了一款无线AR眼镜&#xff0c;虽然还没看过实机&#xff0c;但XDA提前上手体验&#xff0c;我们从中进行总结。首先我要说的是&#xff0c;小米这款眼镜和高通无线AR眼镜参考设计高度重叠&#xff0c;产品卖点几乎一致&#xff0c;只是增…...

Web3中文|Litra:简洁而优美的NFT流动性协议,能给NFT市场带来什么?

2021年&#xff0c;NFT元年2021年&#xff0c;无疑是 NFT 的“元年”。这一年推特创始人的首条推特被拍出250万美元&#xff0c;加密艺术家Beeple的数字作品“First 5000 Days”在佳士得以6900万美元价格成交&#xff0c;无聊猿最高上涨了1800倍。2021年11月&#xff0c;在Goog…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道

文/法律实务观察组 在债务重组领域&#xff0c;专业机构的核心价值不仅在于减轻债务数字&#xff0c;更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明&#xff0c;合法债务优化需同步实现三重平衡&#xff1a; 法律刚性&#xff08;债…...

Xcode 16 集成 cocoapods 报错

基于 Xcode 16 新建工程项目&#xff0c;集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...