@kdcloudjs/table 1.2.2-canary.12 → 1.2.2-canary.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ interface BlankProps {
3
+ height: number;
4
+ className?: string;
5
+ }
6
+ export interface BlankRef {
7
+ updateHeight: (newHeight: number) => void;
8
+ }
9
+ export declare const TopBlank: React.MemoExoticComponent<React.ForwardRefExoticComponent<BlankProps & React.RefAttributes<BlankRef>>>;
10
+ export declare const BottomBlank: React.MemoExoticComponent<React.ForwardRefExoticComponent<BlankProps & React.RefAttributes<BlankRef>>>;
11
+ export {};
@@ -0,0 +1,61 @@
1
+ import _slicedToArray from "@babel/runtime-corejs3/helpers/slicedToArray";
2
+ import React, { useState, useImperativeHandle, forwardRef, memo } from 'react';
3
+ import cx from 'classnames';
4
+ import { Classes } from './styles';
5
+ var TopBlankComponent = /*#__PURE__*/forwardRef(function (_ref, ref) {
6
+ var initialHeight = _ref.height;
7
+ var _useState = useState(initialHeight),
8
+ _useState2 = _slicedToArray(_useState, 2),
9
+ height = _useState2[0],
10
+ setHeight = _useState2[1];
11
+ useImperativeHandle(ref, function () {
12
+ return {
13
+ updateHeight: function updateHeight(newHeight) {
14
+ if (height !== newHeight) {
15
+ setHeight(newHeight);
16
+ }
17
+ }
18
+ };
19
+ }, [height]);
20
+ return /*#__PURE__*/React.createElement("div", {
21
+ style: {
22
+ height: height
23
+ }
24
+ });
25
+ });
26
+ TopBlankComponent.displayName = 'TopBlank';
27
+ var BottomBlankComponent = /*#__PURE__*/forwardRef(function (_ref2, ref) {
28
+ var initialHeight = _ref2.height,
29
+ className = _ref2.className;
30
+ var _useState3 = useState(initialHeight),
31
+ _useState4 = _slicedToArray(_useState3, 2),
32
+ height = _useState4[0],
33
+ setHeight = _useState4[1];
34
+ useImperativeHandle(ref, function () {
35
+ return {
36
+ updateHeight: function updateHeight(newHeight) {
37
+ if (height !== newHeight) {
38
+ setHeight(newHeight);
39
+ }
40
+ }
41
+ };
42
+ }, [height]);
43
+ if (height <= 0) {
44
+ return null;
45
+ }
46
+ return /*#__PURE__*/React.createElement("div", {
47
+ key: "bottom-blank",
48
+ className: cx(Classes.virtualBlank, 'bottom', className),
49
+ style: {
50
+ height: height
51
+ }
52
+ });
53
+ });
54
+ BottomBlankComponent.displayName = 'BottomBlank';
55
+ // 使用 memo 优化,只有当 height 或 className 改变时才重新渲染
56
+ export var TopBlank = /*#__PURE__*/memo(TopBlankComponent, function (prevProps, nextProps) {
57
+ return prevProps.height === nextProps.height && prevProps.className === nextProps.className;
58
+ });
59
+ export var BottomBlank = /*#__PURE__*/memo(BottomBlankComponent, function (prevProps, nextProps) {
60
+ return prevProps.height === nextProps.height && prevProps.className === nextProps.className;
61
+ });
@@ -0,0 +1,96 @@
1
+ /**
2
+ * 快速滚动管理器
3
+ * 抽取 BaseTable 中的快速滚动相关逻辑
4
+ */
5
+ export interface FastScrollConfig {
6
+ /** 预渲染缓冲区大小,用于快速滚动判断 */
7
+ overscanSize?: number;
8
+ /** 快速滚动速度阈值 (像素/毫秒) */
9
+ velocityThreshold?: number;
10
+ /** 快速滚动距离倍数阈值 */
11
+ distanceMultiplier?: number;
12
+ /** 快速滚动结束等待时间 (毫秒) - 高速滚动 */
13
+ fastScrollEndDelayHigh?: number;
14
+ /** 快速滚动结束等待时间 (毫秒) - 普通滚动 */
15
+ fastScrollEndDelayNormal?: number;
16
+ /** 高速滚动速度阈值 (像素/毫秒) */
17
+ highVelocityThreshold?: number;
18
+ }
19
+ export interface FastScrollState {
20
+ lastScrollTime: number;
21
+ scrollVelocity: number;
22
+ lastOffsetY: number;
23
+ }
24
+ export interface ScrollEventData {
25
+ offsetY: number;
26
+ maxRenderHeight: number;
27
+ maxRenderWidth: number;
28
+ }
29
+ export interface VerticalRenderRange {
30
+ topIndex: number;
31
+ bottomIndex: number;
32
+ topBlank: number;
33
+ bottomBlank: number;
34
+ }
35
+ export interface FastScrollCallbacks {
36
+ onFastScrollStart: (renderData: {
37
+ offsetY: number;
38
+ maxRenderHeight: number;
39
+ maxRenderWidth: number;
40
+ verticalRenderRange: VerticalRenderRange;
41
+ }) => void;
42
+ onFastScrollEnd: (scrollData: ScrollEventData) => void;
43
+ getCurrentRenderRange: (offsetY: number, maxRenderHeight: number, dataLength: number) => VerticalRenderRange;
44
+ }
45
+ export declare class FastScrollManager {
46
+ private state;
47
+ private isFastScrolling;
48
+ private fastScrollEndTimer?;
49
+ private config;
50
+ private callbacks;
51
+ constructor(callbacks: FastScrollCallbacks, config?: FastScrollConfig);
52
+ /**
53
+ * 检测是否接近底部(剩余滚动距离少于两屏)
54
+ */
55
+ private isNearBottom;
56
+ /**
57
+ * 处理滚动事件 - 检测和处理快速滚动
58
+ */
59
+ handleScrollEvent(sizeAndOffset: ScrollEventData, currentState: {
60
+ offsetY: number;
61
+ maxRenderHeight: number;
62
+ maxRenderWidth: number;
63
+ }, dataLength: number, totalScrollHeight: number): void;
64
+ /**
65
+ * 开始快速滚动
66
+ */
67
+ private startFastScrolling;
68
+ /**
69
+ * 重置快速滚动结束定时器
70
+ */
71
+ private resetFastScrollEndTimer;
72
+ /**
73
+ * 结束快速滚动
74
+ */
75
+ private endFastScrolling;
76
+ /**
77
+ * 清理资源
78
+ */
79
+ cleanup(): void;
80
+ /**
81
+ * 获取当前是否处于快速滚动状态
82
+ */
83
+ getIsFastScrolling(): boolean;
84
+ /**
85
+ * 获取当前滚动速度
86
+ */
87
+ getScrollVelocity(): number;
88
+ /**
89
+ * 清理资源
90
+ */
91
+ destroy(): void;
92
+ /**
93
+ * 获取当前配置
94
+ */
95
+ getConfig(): Readonly<Required<FastScrollConfig>>;
96
+ }
@@ -0,0 +1,167 @@
1
+ import _extends from "@babel/runtime-corejs3/helpers/extends";
2
+ import _classCallCheck from "@babel/runtime-corejs3/helpers/classCallCheck";
3
+ import _createClass from "@babel/runtime-corejs3/helpers/createClass";
4
+ /**
5
+ * 快速滚动管理器
6
+ * 抽取 BaseTable 中的快速滚动相关逻辑
7
+ */
8
+ export var FastScrollManager = /*#__PURE__*/function () {
9
+ function FastScrollManager(callbacks) {
10
+ var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
11
+ _classCallCheck(this, FastScrollManager);
12
+ // 快速滚动状态
13
+ this.state = {
14
+ lastScrollTime: 0,
15
+ scrollVelocity: 0,
16
+ lastOffsetY: 0
17
+ };
18
+ // 快速滚动标志 - 作为私有属性立即更新
19
+ this.isFastScrolling = false;
20
+ this.callbacks = callbacks;
21
+ // 合并默认配置
22
+ this.config = _extends({
23
+ overscanSize: 100,
24
+ velocityThreshold: 3,
25
+ distanceMultiplier: 3,
26
+ fastScrollEndDelayHigh: 200,
27
+ fastScrollEndDelayNormal: 150,
28
+ highVelocityThreshold: 5
29
+ }, config);
30
+ }
31
+ /**
32
+ * 检测是否接近底部(剩余滚动距离少于两屏)
33
+ */
34
+ _createClass(FastScrollManager, [{
35
+ key: "isNearBottom",
36
+ value: function isNearBottom(currentScrollTop, maxRenderHeight, totalScrollHeight) {
37
+ var remainingScrollDistance = totalScrollHeight - currentScrollTop - maxRenderHeight;
38
+ return remainingScrollDistance < maxRenderHeight;
39
+ }
40
+ /**
41
+ * 处理滚动事件 - 检测和处理快速滚动
42
+ */
43
+ }, {
44
+ key: "handleScrollEvent",
45
+ value: function handleScrollEvent(sizeAndOffset, currentState, dataLength, totalScrollHeight) {
46
+ var currentTime = performance.now();
47
+ var deltaY = Math.abs(sizeAndOffset.offsetY - this.state.lastOffsetY);
48
+ var deltaTime = currentTime - this.state.lastScrollTime;
49
+ // 计算滚动速度 (像素/毫秒)
50
+ this.state.scrollVelocity = deltaTime > 0 ? deltaY / deltaTime : 0;
51
+ // 检测是否接近底部
52
+ var isNearBottom = this.isNearBottom(sizeAndOffset.offsetY, sizeAndOffset.maxRenderHeight, totalScrollHeight);
53
+ // 如果正在快速滚动但接近底部,提前结束快速滚动
54
+ if (this.isFastScrolling && isNearBottom) {
55
+ this.endFastScrolling(sizeAndOffset);
56
+ return; // 让正常渲染逻辑接管
57
+ }
58
+ // 快速滚动判断条件:
59
+ // 1. 滚动距离超过阈值 && 滚动速度超过阈值
60
+ // 2. 当前未在快速滚动状态
61
+ // 3. 未接近底部边界
62
+ var isSignificantChange = deltaY > this.config.overscanSize * this.config.distanceMultiplier;
63
+ var isHighVelocity = this.state.scrollVelocity > this.config.velocityThreshold;
64
+ var shouldStartFastScroll = (isSignificantChange || isHighVelocity) && !this.isFastScrolling && !isNearBottom; // 接近底部时不启动快速滚动
65
+ if (shouldStartFastScroll) {
66
+ this.startFastScrolling(currentState, dataLength);
67
+ }
68
+ // 重置快速滚动结束定时器
69
+ if (this.isFastScrolling) {
70
+ this.resetFastScrollEndTimer(sizeAndOffset);
71
+ }
72
+ // 更新记录
73
+ this.state.lastOffsetY = sizeAndOffset.offsetY;
74
+ this.state.lastScrollTime = currentTime;
75
+ }
76
+ /**
77
+ * 开始快速滚动
78
+ */
79
+ }, {
80
+ key: "startFastScrolling",
81
+ value: function startFastScrolling(currentState, dataLength) {
82
+ this.isFastScrolling = true;
83
+ // 获取当前渲染范围作为缓存
84
+ var currentVerticalRange = this.callbacks.getCurrentRenderRange(currentState.offsetY, currentState.maxRenderHeight, dataLength);
85
+ // 通知外部开始快速滚动
86
+ this.callbacks.onFastScrollStart({
87
+ offsetY: currentState.offsetY,
88
+ maxRenderHeight: currentState.maxRenderHeight,
89
+ maxRenderWidth: currentState.maxRenderWidth,
90
+ verticalRenderRange: currentVerticalRange
91
+ });
92
+ }
93
+ /**
94
+ * 重置快速滚动结束定时器
95
+ */
96
+ }, {
97
+ key: "resetFastScrollEndTimer",
98
+ value: function resetFastScrollEndTimer(sizeAndOffset) {
99
+ var _this = this;
100
+ if (this.fastScrollEndTimer) {
101
+ clearTimeout(this.fastScrollEndTimer);
102
+ }
103
+ var waitTime = this.state.scrollVelocity > this.config.highVelocityThreshold ? this.config.fastScrollEndDelayHigh : this.config.fastScrollEndDelayNormal;
104
+ this.fastScrollEndTimer = window.setTimeout(function () {
105
+ _this.endFastScrolling(sizeAndOffset);
106
+ }, waitTime);
107
+ }
108
+ /**
109
+ * 结束快速滚动
110
+ */
111
+ }, {
112
+ key: "endFastScrolling",
113
+ value: function endFastScrolling(sizeAndOffset) {
114
+ this.isFastScrolling = false;
115
+ this.fastScrollEndTimer = undefined;
116
+ // 通知外部结束快速滚动
117
+ this.callbacks.onFastScrollEnd(sizeAndOffset);
118
+ }
119
+ /**
120
+ * 清理资源
121
+ */
122
+ }, {
123
+ key: "cleanup",
124
+ value: function cleanup() {
125
+ if (this.fastScrollEndTimer) {
126
+ clearTimeout(this.fastScrollEndTimer);
127
+ }
128
+ }
129
+ /**
130
+ * 获取当前是否处于快速滚动状态
131
+ */
132
+ }, {
133
+ key: "getIsFastScrolling",
134
+ value: function getIsFastScrolling() {
135
+ return this.isFastScrolling;
136
+ }
137
+ /**
138
+ * 获取当前滚动速度
139
+ */
140
+ }, {
141
+ key: "getScrollVelocity",
142
+ value: function getScrollVelocity() {
143
+ return this.state.scrollVelocity;
144
+ }
145
+ /**
146
+ * 清理资源
147
+ */
148
+ }, {
149
+ key: "destroy",
150
+ value: function destroy() {
151
+ if (this.fastScrollEndTimer) {
152
+ clearTimeout(this.fastScrollEndTimer);
153
+ this.fastScrollEndTimer = undefined;
154
+ }
155
+ this.isFastScrolling = false;
156
+ }
157
+ /**
158
+ * 获取当前配置
159
+ */
160
+ }, {
161
+ key: "getConfig",
162
+ value: function getConfig() {
163
+ return _extends({}, this.config);
164
+ }
165
+ }]);
166
+ return FastScrollManager;
167
+ }();
@@ -23,6 +23,8 @@ export interface BaseTableProps {
23
23
  };
24
24
  /** 虚拟滚动开启情况下,表格中每一行的预估高度 */
25
25
  estimatedRowHeight?: number;
26
+ /** 性能差浏览器和处理器,性能差则启动快速滚动优化,默认为 false */
27
+ isLowPerformance?: boolean;
26
28
  /** @deprecated 表格头部是否置顶,默认为 true。请使用 isStickyHeader 代替 */
27
29
  isStickyHead?: boolean;
28
30
  /** 表格头部是否置顶,默认为 true */
@@ -107,6 +109,13 @@ export interface BaseTableState {
107
109
  offsetX: number;
108
110
  /** 横向虚拟滚动 最大渲染尺寸 */
109
111
  maxRenderWidth: number;
112
+ /** 快速滚动时保留的上一次渲染数据 */
113
+ previousRenderData?: {
114
+ offsetY: number;
115
+ maxRenderHeight: number;
116
+ maxRenderWidth: number;
117
+ verticalRenderRange: VerticalRenderRange;
118
+ };
110
119
  }
111
120
  export declare class BaseTable extends React.Component<BaseTableProps, BaseTableState> {
112
121
  static defaultProps: {
@@ -120,6 +129,7 @@ export declare class BaseTable extends React.Component<BaseTableProps, BaseTable
120
129
  stickyScrollHeight: string;
121
130
  useVirtual: string;
122
131
  estimatedRowHeight: number;
132
+ isLowPerformance: boolean;
123
133
  isLoading: boolean;
124
134
  components: {};
125
135
  getTableProps: typeof noop;
@@ -137,6 +147,9 @@ export declare class BaseTable extends React.Component<BaseTableProps, BaseTable
137
147
  private hasScrollY;
138
148
  private resizeObserver?;
139
149
  private offsetY;
150
+ private fastScrollManager;
151
+ private topBlankRef;
152
+ private bottomBlankRef;
140
153
  /** @deprecated BaseTable.getDoms() 已经过时,请勿调用 */
141
154
  getDoms(): TableDOMHelper;
142
155
  constructor(props: Readonly<BaseTableProps>);