stk-table-vue 0.3.2 → 0.3.3
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.
- package/README.md +11 -0
- package/lib/src/StkTable/StkTable.vue.d.ts +21 -2
- package/lib/src/StkTable/useColResize.d.ts +3 -3
- package/lib/src/StkTable/useFixedCol.d.ts +4 -4
- package/lib/src/StkTable/useVirtualScroll.d.ts +4 -1
- package/lib/stk-table-vue.js +55 -35
- package/lib/style.css +6 -12
- package/package.json +1 -1
- package/src/StkTable/StkTable.vue +33 -17
- package/src/StkTable/style.less +16 -37
- package/src/StkTable/useColResize.ts +5 -5
- package/src/StkTable/useFixedCol.ts +4 -4
- package/src/StkTable/useFixedStyle.ts +29 -8
- package/src/StkTable/useVirtualScroll.ts +8 -5
package/README.md
CHANGED
|
@@ -231,6 +231,14 @@ export type StkProps = {
|
|
|
231
231
|
/** 序号列起始下标 用于适配分页 */
|
|
232
232
|
startIndex?: number;
|
|
233
233
|
};
|
|
234
|
+
/**
|
|
235
|
+
* 固定头,固定列实现方式。
|
|
236
|
+
*
|
|
237
|
+
* relative:固定列只能放在props.columns的两侧。如果列宽会变动则谨慎使用。
|
|
238
|
+
*
|
|
239
|
+
* 低版本浏览器只能为'relative',
|
|
240
|
+
*/
|
|
241
|
+
cellFixedMode?: 'sticky' | 'relative';
|
|
234
242
|
};
|
|
235
243
|
```
|
|
236
244
|
|
|
@@ -545,6 +553,9 @@ export type SortConfig<T extends Record<string, any>> = {
|
|
|
545
553
|
* 在虚拟滚动下高亮强制使用css @keyframes 实现动画。`setHighlightDimRow`/`setHighlightCellRow` 最后一个参数传入 `{method: 'css'}` 即可。(滚动后动画会中断)
|
|
546
554
|
* 指定 `{method:'animation'}` 在虚拟滚动下使用animation api实现动画。好处是动画流畅,且滚动后动画不中断。
|
|
547
555
|
* 配置 `props.highlightConfig.fps` 指定高亮帧率。降低帧率有利于性能。
|
|
556
|
+
### 性能
|
|
557
|
+
* 配置 `props.cellFixedMode` 为 `relative` 时,将使用相对定位实现固定列与固定表头,相较于`sticky`的实现,渲染合成层更少,性能更好。
|
|
558
|
+
* 问题:若开启了纵向虚拟滚动,不开启横向虚拟滚动,且不设置某些列宽时。如果纵向滚动导致某些列宽变化,则会导致右侧固定列计算错误。
|
|
548
559
|
|
|
549
560
|
## Other
|
|
550
561
|
* `$*$` 兼容注释
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HighlightConfig, Order, SeqConfig, SortConfig, SortOption, SortState, StkTableColumn, UniqKeyProp } from './types/index';
|
|
1
|
+
import { HighlightConfig, Order, SeqConfig, SortConfig, SortOption, SortState, StkTableColumn, UniqKey, UniqKeyProp } from './types/index';
|
|
2
2
|
/** Generic stands for DataType */
|
|
3
3
|
type DT = any;
|
|
4
4
|
/**
|
|
@@ -126,6 +126,14 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
126
126
|
highlightConfig?: HighlightConfig | undefined;
|
|
127
127
|
/** 序号列配置 */
|
|
128
128
|
seqConfig?: SeqConfig | undefined;
|
|
129
|
+
/**
|
|
130
|
+
* 固定头,固定列实现方式。
|
|
131
|
+
*
|
|
132
|
+
* relative:固定列只能放在props.columns的两侧。如果列宽会变动则谨慎使用。
|
|
133
|
+
*
|
|
134
|
+
* 低版本浏览器只能为'relative',
|
|
135
|
+
*/
|
|
136
|
+
cellFixedMode?: "sticky" | "relative" | undefined;
|
|
129
137
|
}>, {
|
|
130
138
|
width: string;
|
|
131
139
|
fixedMode: boolean;
|
|
@@ -165,6 +173,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
165
173
|
hideHeaderTitle: boolean;
|
|
166
174
|
highlightConfig: () => {};
|
|
167
175
|
seqConfig: () => {};
|
|
176
|
+
cellFixedMode: string;
|
|
168
177
|
}>, {
|
|
169
178
|
/** 初始化横向纵向虚拟滚动 */
|
|
170
179
|
initVirtualScroll: (height?: number | undefined) => void;
|
|
@@ -182,7 +191,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
182
191
|
duration?: number | undefined;
|
|
183
192
|
}) => void;
|
|
184
193
|
/** 设置高亮渐暗行 */
|
|
185
|
-
setHighlightDimRow: (rowKeyValues:
|
|
194
|
+
setHighlightDimRow: (rowKeyValues: UniqKey[], option?: {
|
|
186
195
|
method?: "css" | "animation" | "js" | undefined;
|
|
187
196
|
useCss?: boolean | undefined;
|
|
188
197
|
className?: string | undefined;
|
|
@@ -314,6 +323,14 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
314
323
|
highlightConfig?: HighlightConfig | undefined;
|
|
315
324
|
/** 序号列配置 */
|
|
316
325
|
seqConfig?: SeqConfig | undefined;
|
|
326
|
+
/**
|
|
327
|
+
* 固定头,固定列实现方式。
|
|
328
|
+
*
|
|
329
|
+
* relative:固定列只能放在props.columns的两侧。如果列宽会变动则谨慎使用。
|
|
330
|
+
*
|
|
331
|
+
* 低版本浏览器只能为'relative',
|
|
332
|
+
*/
|
|
333
|
+
cellFixedMode?: "sticky" | "relative" | undefined;
|
|
317
334
|
}>, {
|
|
318
335
|
width: string;
|
|
319
336
|
fixedMode: boolean;
|
|
@@ -353,6 +370,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
353
370
|
hideHeaderTitle: boolean;
|
|
354
371
|
highlightConfig: () => {};
|
|
355
372
|
seqConfig: () => {};
|
|
373
|
+
cellFixedMode: string;
|
|
356
374
|
}>>> & {
|
|
357
375
|
onScroll?: ((ev: Event, data: {
|
|
358
376
|
startIndex: number;
|
|
@@ -415,6 +433,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
|
|
|
415
433
|
hideHeaderTitle: boolean | string[];
|
|
416
434
|
highlightConfig: HighlightConfig;
|
|
417
435
|
seqConfig: SeqConfig;
|
|
436
|
+
cellFixedMode: "sticky" | "relative";
|
|
418
437
|
}, {}>, {
|
|
419
438
|
tableHeader?(_: {
|
|
420
439
|
col: StkTableColumn<any>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { Ref, ShallowRef } from 'vue';
|
|
2
|
-
import { StkTableColumn } from './types';
|
|
1
|
+
import { ComputedRef, Ref, ShallowRef } from 'vue';
|
|
2
|
+
import { StkTableColumn, UniqKey } from './types';
|
|
3
3
|
type Params<DT extends Record<string, any>> = {
|
|
4
4
|
props: any;
|
|
5
5
|
emits: any;
|
|
6
6
|
tableContainerRef: Ref<HTMLElement | undefined>;
|
|
7
7
|
tableHeaderLast: ShallowRef<StkTableColumn<DT>[]>;
|
|
8
8
|
colResizeIndicatorRef: Ref<HTMLElement | undefined>;
|
|
9
|
-
colKeyGen: (p: any) =>
|
|
9
|
+
colKeyGen: ComputedRef<(p: any) => UniqKey>;
|
|
10
10
|
};
|
|
11
11
|
/** 列宽拖动 */
|
|
12
12
|
export declare function useColResize<DT extends Record<string, any>>({ tableContainerRef, tableHeaderLast, colResizeIndicatorRef, props, emits, colKeyGen, }: Params<DT>): {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Ref, ShallowRef } from 'vue';
|
|
2
|
-
import { StkTableColumn } from './types';
|
|
1
|
+
import { ComputedRef, Ref, ShallowRef } from 'vue';
|
|
2
|
+
import { StkTableColumn, UniqKey } from './types';
|
|
3
3
|
type Params<T extends Record<string, any>> = {
|
|
4
4
|
props: any;
|
|
5
|
-
colKeyGen: (col: StkTableColumn<T>) =>
|
|
5
|
+
colKeyGen: ComputedRef<(col: StkTableColumn<T>) => UniqKey>;
|
|
6
6
|
tableHeaders: ShallowRef<StkTableColumn<T>[][]>;
|
|
7
7
|
tableHeaderLast: ShallowRef<StkTableColumn<T>[]>;
|
|
8
8
|
tableContainerRef: Ref<HTMLDivElement | undefined>;
|
|
@@ -13,7 +13,7 @@ type Params<T extends Record<string, any>> = {
|
|
|
13
13
|
*/
|
|
14
14
|
export declare function useFixedCol<DT extends Record<string, any>>({ props, colKeyGen, tableHeaders, tableHeaderLast, tableContainerRef }: Params<DT>): {
|
|
15
15
|
/** 固定列class */
|
|
16
|
-
fixedColClassMap:
|
|
16
|
+
fixedColClassMap: ComputedRef<Map<any, any>>;
|
|
17
17
|
/** 处理固定列阴影 */
|
|
18
18
|
dealFixedColShadow: () => void;
|
|
19
19
|
/** 滚动条变化时,更新需要展示阴影的列 */
|
|
@@ -26,8 +26,10 @@ export type VirtualScrollStore = {
|
|
|
26
26
|
};
|
|
27
27
|
/** 暂存横向虚拟滚动的数据 */
|
|
28
28
|
export type VirtualScrollXStore = {
|
|
29
|
-
/**
|
|
29
|
+
/** 父容器宽度 */
|
|
30
30
|
containerWidth: number;
|
|
31
|
+
/** 滚动容器的宽度 */
|
|
32
|
+
scrollWidth: number;
|
|
31
33
|
/** 开始位置 */
|
|
32
34
|
startIndex: number;
|
|
33
35
|
/** 结束始位置 */
|
|
@@ -54,6 +56,7 @@ export declare function useVirtualScroll<DT extends Record<string, any>>({ props
|
|
|
54
56
|
}>;
|
|
55
57
|
virtualScrollX: Ref<{
|
|
56
58
|
containerWidth: number;
|
|
59
|
+
scrollWidth: number;
|
|
57
60
|
startIndex: number;
|
|
58
61
|
endIndex: number;
|
|
59
62
|
offsetLeft: number;
|
package/lib/stk-table-vue.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { onMounted, onBeforeUnmount, watch, ref, shallowRef, computed, defineComponent, toRaw, openBlock, createElementBlock, normalizeClass, unref, normalizeStyle, createCommentVNode, createElementVNode, Fragment, renderList, createBlock, resolveDynamicComponent, toDisplayString, renderSlot, createTextVNode } from "vue";
|
|
1
|
+
import { onMounted, onBeforeUnmount, watch, ref, shallowRef, computed, defineComponent, nextTick, toRaw, openBlock, createElementBlock, normalizeClass, unref, normalizeStyle, createCommentVNode, createElementVNode, Fragment, renderList, createBlock, resolveDynamicComponent, toDisplayString, renderSlot, createTextVNode } from "vue";
|
|
2
2
|
import { interpolateRgb } from "d3-interpolate";
|
|
3
3
|
const DEFAULT_COL_WIDTH = "100";
|
|
4
4
|
const DEFAULT_TABLE_HEIGHT = 100;
|
|
@@ -260,7 +260,7 @@ function useColResize({
|
|
|
260
260
|
const { clientX } = e;
|
|
261
261
|
const { scrollLeft, scrollTop } = tableContainerRef.value;
|
|
262
262
|
const { left } = tableContainerRef.value.getBoundingClientRect();
|
|
263
|
-
let colIndex = tableHeaderLast.value.findIndex((it) => colKeyGen(it) === colKeyGen(col));
|
|
263
|
+
let colIndex = tableHeaderLast.value.findIndex((it) => colKeyGen.value(it) === colKeyGen.value(col));
|
|
264
264
|
if (isPrev) {
|
|
265
265
|
colIndex -= 1;
|
|
266
266
|
col = tableHeaderLast.value[colIndex];
|
|
@@ -307,7 +307,7 @@ function useColResize({
|
|
|
307
307
|
let width = getCalculatedColWidth(lastCol) + moveX;
|
|
308
308
|
if (width < props.colMinWidth)
|
|
309
309
|
width = props.colMinWidth;
|
|
310
|
-
const curCol = tableHeaderLast.value.find((it) => colKeyGen(it) === colKeyGen(lastCol));
|
|
310
|
+
const curCol = tableHeaderLast.value.find((it) => colKeyGen.value(it) === colKeyGen.value(lastCol));
|
|
311
311
|
if (!curCol)
|
|
312
312
|
return;
|
|
313
313
|
curCol.width = width + "px";
|
|
@@ -359,7 +359,7 @@ function useFixedCol({ props, colKeyGen, tableHeaders, tableHeaderLast, tableCon
|
|
|
359
359
|
["fixed-cell--" + col.fixed]: col.fixed,
|
|
360
360
|
"fixed-cell--shadow": showShadow
|
|
361
361
|
};
|
|
362
|
-
colMap.set(colKeyGen(col), classObj);
|
|
362
|
+
colMap.set(colKeyGen.value(col), classObj);
|
|
363
363
|
});
|
|
364
364
|
});
|
|
365
365
|
return colMap;
|
|
@@ -453,33 +453,45 @@ function useFixedStyle({
|
|
|
453
453
|
const { fixed } = col;
|
|
454
454
|
if (tagType === TagType.TD && !fixed)
|
|
455
455
|
return null;
|
|
456
|
-
const isFixedLeft = fixed === "left";
|
|
457
456
|
const style = {};
|
|
458
457
|
const { colKeyStore, refStore } = fixedColumnsPositionStore.value;
|
|
458
|
+
let isRelativeMode = true;
|
|
459
|
+
if (props.cellFixedMode === "sticky") {
|
|
460
|
+
isRelativeMode = false;
|
|
461
|
+
}
|
|
459
462
|
if (IS_LEGACY_MODE) {
|
|
463
|
+
isRelativeMode = true;
|
|
464
|
+
}
|
|
465
|
+
const { scrollLeft, scrollWidth, offsetLeft, containerWidth } = virtualScrollX.value;
|
|
466
|
+
const scrollRight = scrollWidth - containerWidth - scrollLeft;
|
|
467
|
+
if (virtualScrollX.value.scrollLeft === 0 && fixed === "left" && tagType === TagType.TD) {
|
|
468
|
+
style.position = void 0;
|
|
469
|
+
} else if (scrollRight === 0 && fixed === "right" && tagType === TagType.TD) {
|
|
470
|
+
style.position = void 0;
|
|
471
|
+
} else if (isRelativeMode) {
|
|
460
472
|
style.position = "relative";
|
|
461
473
|
} else {
|
|
462
474
|
style.position = "sticky";
|
|
463
475
|
}
|
|
476
|
+
const isFixedLeft = fixed === "left";
|
|
464
477
|
if (tagType === TagType.TH) {
|
|
465
|
-
if (
|
|
478
|
+
if (isRelativeMode) {
|
|
466
479
|
style.top = virtualScroll.value.scrollTop + "px";
|
|
467
480
|
} else {
|
|
468
481
|
style.top = depth * props.rowHeight + "px";
|
|
469
482
|
}
|
|
470
483
|
style.zIndex = isFixedLeft ? "3" : "2";
|
|
471
484
|
} else {
|
|
472
|
-
|
|
485
|
+
if (isFixedLeft) {
|
|
486
|
+
style.zIndex = "2";
|
|
487
|
+
}
|
|
473
488
|
}
|
|
474
489
|
if (fixed === "left" || fixed === "right") {
|
|
475
|
-
if (
|
|
490
|
+
if (isRelativeMode) {
|
|
476
491
|
if (isFixedLeft) {
|
|
477
|
-
|
|
478
|
-
style.left = virtualScrollX.value.scrollLeft - virtualScrollX.value.offsetLeft + "px";
|
|
479
|
-
else
|
|
480
|
-
style.left = virtualScrollX.value.scrollLeft + "px";
|
|
492
|
+
style.left = scrollLeft - (virtualX_on.value ? offsetLeft : 0) + "px";
|
|
481
493
|
} else {
|
|
482
|
-
style.right =
|
|
494
|
+
style.right = Math.max(scrollRight - (virtualX_on.value ? virtualX_offsetRight.value : 0), 0) + "px";
|
|
483
495
|
}
|
|
484
496
|
} else {
|
|
485
497
|
const lr = (col.dataIndex ? colKeyStore[col.dataIndex] : refStore.get(col)) + "px";
|
|
@@ -837,6 +849,7 @@ function useVirtualScroll({
|
|
|
837
849
|
});
|
|
838
850
|
const virtualScrollX = ref({
|
|
839
851
|
containerWidth: 0,
|
|
852
|
+
scrollWidth: 0,
|
|
840
853
|
startIndex: 0,
|
|
841
854
|
endIndex: 0,
|
|
842
855
|
offsetLeft: 0,
|
|
@@ -913,10 +926,9 @@ function useVirtualScroll({
|
|
|
913
926
|
updateVirtualScrollY(scrollTop);
|
|
914
927
|
}
|
|
915
928
|
function initVirtualScrollX() {
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
virtualScrollX.value.containerWidth = offsetWidth || DEFAULT_TABLE_WIDTH;
|
|
929
|
+
const { clientWidth, scrollLeft, scrollWidth } = tableContainerRef.value || {};
|
|
930
|
+
virtualScrollX.value.containerWidth = clientWidth || DEFAULT_TABLE_WIDTH;
|
|
931
|
+
virtualScrollX.value.scrollWidth = scrollWidth || DEFAULT_TABLE_WIDTH;
|
|
920
932
|
updateVirtualScrollX(scrollLeft);
|
|
921
933
|
}
|
|
922
934
|
function initVirtualScroll(height) {
|
|
@@ -969,6 +981,8 @@ function useVirtualScroll({
|
|
|
969
981
|
let vue2ScrollXTimeout = null;
|
|
970
982
|
function updateVirtualScrollX(sLeft = 0) {
|
|
971
983
|
var _a;
|
|
984
|
+
if (!props.virtualX)
|
|
985
|
+
return;
|
|
972
986
|
const headerLength = (_a = tableHeaderLast.value) == null ? void 0 : _a.length;
|
|
973
987
|
const { scrollLeft } = virtualScrollX.value;
|
|
974
988
|
if (!headerLength)
|
|
@@ -1068,14 +1082,12 @@ const _hoisted_9 = ["onMousedown"];
|
|
|
1068
1082
|
const _hoisted_10 = ["onMousedown"];
|
|
1069
1083
|
const _hoisted_11 = {
|
|
1070
1084
|
key: 0,
|
|
1071
|
-
class: "virtual-x-left"
|
|
1072
|
-
style: { "padding": "0" }
|
|
1085
|
+
class: "virtual-x-left"
|
|
1073
1086
|
};
|
|
1074
1087
|
const _hoisted_12 = ["id", "data-row-key", "onClick", "onDblclick", "onContextmenu", "onMouseover"];
|
|
1075
1088
|
const _hoisted_13 = {
|
|
1076
1089
|
key: 0,
|
|
1077
|
-
class: "virtual-x-left"
|
|
1078
|
-
style: { "padding": "0" }
|
|
1090
|
+
class: "virtual-x-left"
|
|
1079
1091
|
};
|
|
1080
1092
|
const _hoisted_14 = ["data-index", "onClick", "onMouseenter", "onMouseleave", "onMouseover"];
|
|
1081
1093
|
const _hoisted_15 = ["title"];
|
|
@@ -1119,7 +1131,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1119
1131
|
}) },
|
|
1120
1132
|
hideHeaderTitle: { type: [Boolean, Array], default: false },
|
|
1121
1133
|
highlightConfig: { default: () => ({}) },
|
|
1122
|
-
seqConfig: { default: () => ({}) }
|
|
1134
|
+
seqConfig: { default: () => ({}) },
|
|
1135
|
+
cellFixedMode: { default: "sticky" }
|
|
1123
1136
|
},
|
|
1124
1137
|
emits: ["sort-change", "row-click", "current-change", "row-dblclick", "header-row-menu", "row-menu", "cell-click", "cell-mouseenter", "cell-mouseleave", "cell-mouseover", "header-cell-click", "scroll", "scroll-x", "col-order-change", "th-drag-start", "th-drop", "update:columns"],
|
|
1125
1138
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
@@ -1138,6 +1151,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1138
1151
|
const tableHeaders = shallowRef([]);
|
|
1139
1152
|
const tableHeaderLast = shallowRef([]);
|
|
1140
1153
|
const dataSourceCopy = shallowRef([...props.dataSource]);
|
|
1154
|
+
const colKeyGen = computed(() => {
|
|
1155
|
+
if (typeof props.colKey === "function") {
|
|
1156
|
+
return (col) => props.colKey(col);
|
|
1157
|
+
} else {
|
|
1158
|
+
return (col) => col[props.colKey];
|
|
1159
|
+
}
|
|
1160
|
+
});
|
|
1141
1161
|
const getEmptyCellText = computed(() => {
|
|
1142
1162
|
if (typeof props.emptyCellText === "string") {
|
|
1143
1163
|
return () => props.emptyCellText;
|
|
@@ -1201,14 +1221,16 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1201
1221
|
() => props.columns,
|
|
1202
1222
|
() => {
|
|
1203
1223
|
dealColumns();
|
|
1204
|
-
initVirtualScrollX
|
|
1224
|
+
nextTick(initVirtualScrollX);
|
|
1205
1225
|
}
|
|
1206
1226
|
);
|
|
1207
1227
|
watch(
|
|
1208
1228
|
() => props.virtualX,
|
|
1209
|
-
() =>
|
|
1229
|
+
() => {
|
|
1230
|
+
dealColumns();
|
|
1231
|
+
nextTick(initVirtualScrollX);
|
|
1232
|
+
}
|
|
1210
1233
|
);
|
|
1211
|
-
dealColumns();
|
|
1212
1234
|
watch(
|
|
1213
1235
|
() => props.dataSource,
|
|
1214
1236
|
(val) => {
|
|
@@ -1234,6 +1256,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1234
1256
|
}
|
|
1235
1257
|
);
|
|
1236
1258
|
watch(() => props.fixedColShadow, dealFixedColShadow);
|
|
1259
|
+
dealColumns();
|
|
1237
1260
|
onMounted(() => {
|
|
1238
1261
|
initVirtualScroll();
|
|
1239
1262
|
updateFixedShadow();
|
|
@@ -1305,15 +1328,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1305
1328
|
}
|
|
1306
1329
|
return key;
|
|
1307
1330
|
}
|
|
1308
|
-
function colKeyGen(col) {
|
|
1309
|
-
return typeof props.colKey === "function" ? props.colKey(col) : col[props.colKey];
|
|
1310
|
-
}
|
|
1311
1331
|
const cellStyleMap = computed(() => {
|
|
1312
1332
|
const thMap = /* @__PURE__ */ new Map();
|
|
1313
1333
|
const tdMap = /* @__PURE__ */ new Map();
|
|
1314
1334
|
tableHeaders.value.forEach((cols, depth) => {
|
|
1315
1335
|
cols.forEach((col) => {
|
|
1316
|
-
const colKey = colKeyGen(col);
|
|
1336
|
+
const colKey = colKeyGen.value(col);
|
|
1317
1337
|
const width = props.virtualX ? getCalculatedColWidth(col) + "px" : transformWidthToStr(col.width);
|
|
1318
1338
|
const style = {
|
|
1319
1339
|
width
|
|
@@ -1592,17 +1612,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1592
1612
|
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(virtualX_on) && rowIndex === tableHeaders.value.length - 1 ? unref(virtualX_columnPart) : row, (col, colIndex) => {
|
|
1593
1613
|
return openBlock(), createElementBlock("th", {
|
|
1594
1614
|
key: col.dataIndex,
|
|
1595
|
-
"data-col-key": colKeyGen(col),
|
|
1615
|
+
"data-col-key": colKeyGen.value(col),
|
|
1596
1616
|
draggable: unref(isHeaderDraggable)(col) ? "true" : "false",
|
|
1597
1617
|
rowspan: unref(virtualX_on) ? 1 : col.rowSpan,
|
|
1598
1618
|
colspan: col.colSpan,
|
|
1599
|
-
style: normalizeStyle(cellStyleMap.value[unref(TagType).TH].get(colKeyGen(col))),
|
|
1619
|
+
style: normalizeStyle(cellStyleMap.value[unref(TagType).TH].get(colKeyGen.value(col))),
|
|
1600
1620
|
title: getHeaderTitle(col),
|
|
1601
1621
|
class: normalizeClass([
|
|
1602
1622
|
col.sorter ? "sortable" : "",
|
|
1603
1623
|
col.dataIndex === unref(sortCol) && unref(sortOrderIndex) !== 0 && "sorter-" + sortSwitchOrder[unref(sortOrderIndex)],
|
|
1604
1624
|
col.headerClassName,
|
|
1605
|
-
unref(fixedColClassMap).get(colKeyGen(col))
|
|
1625
|
+
unref(fixedColClassMap).get(colKeyGen.value(col))
|
|
1606
1626
|
]),
|
|
1607
1627
|
onClick: (e) => {
|
|
1608
1628
|
onColumnSort(col);
|
|
@@ -1660,7 +1680,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1660
1680
|
_ctx.fixedMode && _ctx.headless ? (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(unref(virtualX_columnPart), (col) => {
|
|
1661
1681
|
return openBlock(), createElementBlock("td", {
|
|
1662
1682
|
key: col.dataIndex,
|
|
1663
|
-
style: normalizeStyle(cellStyleMap.value[unref(TagType).TD].get(colKeyGen(col)))
|
|
1683
|
+
style: normalizeStyle(cellStyleMap.value[unref(TagType).TD].get(colKeyGen.value(col)))
|
|
1664
1684
|
}, null, 4);
|
|
1665
1685
|
}), 128)) : createCommentVNode("", true)
|
|
1666
1686
|
], 4)) : createCommentVNode("", true),
|
|
@@ -1684,8 +1704,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1684
1704
|
return openBlock(), createElementBlock("td", {
|
|
1685
1705
|
key: col.dataIndex,
|
|
1686
1706
|
"data-index": col.dataIndex,
|
|
1687
|
-
style: normalizeStyle(cellStyleMap.value[unref(TagType).TD].get(colKeyGen(col))),
|
|
1688
|
-
class: normalizeClass([col.className, unref(fixedColClassMap).get(colKeyGen(col)), col.type === "seq" ? "seq-column" : ""]),
|
|
1707
|
+
style: normalizeStyle(cellStyleMap.value[unref(TagType).TD].get(colKeyGen.value(col))),
|
|
1708
|
+
class: normalizeClass([col.className, unref(fixedColClassMap).get(colKeyGen.value(col)), col.type === "seq" ? "seq-column" : ""]),
|
|
1689
1709
|
onClick: (e) => onCellClick(e, row, col),
|
|
1690
1710
|
onMouseenter: (e) => onCellMouseEnter(e, row, col),
|
|
1691
1711
|
onMouseleave: (e) => onCellMouseLeave(e, row, col),
|
package/lib/style.css
CHANGED
|
@@ -88,15 +88,6 @@
|
|
|
88
88
|
.stk-table.border thead tr:first-child th{
|
|
89
89
|
background-image:var(--bg-border-top), var(--bg-border-right), var(--bg-border-bottom);
|
|
90
90
|
}
|
|
91
|
-
.stk-table.border.virtual-x .virtual-x-left{
|
|
92
|
-
background:none;
|
|
93
|
-
pointer-events:none;
|
|
94
|
-
}
|
|
95
|
-
.stk-table.border.virtual-x .virtual-x-right{
|
|
96
|
-
padding:0;
|
|
97
|
-
background:none;
|
|
98
|
-
pointer-events:none;
|
|
99
|
-
}
|
|
100
91
|
.stk-table.border-body-v tbody{
|
|
101
92
|
--bg-border-bottom:linear-gradient(transparent, transparent);
|
|
102
93
|
}
|
|
@@ -136,9 +127,6 @@
|
|
|
136
127
|
.stk-table.virtual .padding-top-tr td{
|
|
137
128
|
height:0;
|
|
138
129
|
}
|
|
139
|
-
.stk-table.virtual-x .virtual-x-left{
|
|
140
|
-
padding:0;
|
|
141
|
-
}
|
|
142
130
|
.stk-table th,
|
|
143
131
|
.stk-table td{
|
|
144
132
|
z-index:1;
|
|
@@ -197,6 +185,12 @@
|
|
|
197
185
|
.stk-table .stk-table-main tbody tr.active{
|
|
198
186
|
background-color:var(--tr-active-bgc);
|
|
199
187
|
}
|
|
188
|
+
.stk-table .virtual-x-left,
|
|
189
|
+
.stk-table .virtual-x-right{
|
|
190
|
+
padding:0;
|
|
191
|
+
background:none;
|
|
192
|
+
pointer-events:none;
|
|
193
|
+
}
|
|
200
194
|
.stk-table .column-resize-indicator{
|
|
201
195
|
width:0;
|
|
202
196
|
height:100%;
|
package/package.json
CHANGED
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
<tbody>
|
|
143
143
|
<tr v-if="virtual_on" :style="{ height: `${virtualScroll.offsetTop}px` }" class="padding-top-tr">
|
|
144
144
|
<!--这个td用于配合虚拟滚动的th对应,防止列错位-->
|
|
145
|
-
<td v-if="virtualX_on && fixedMode && headless" class="virtual-x-left"
|
|
145
|
+
<td v-if="virtualX_on && fixedMode && headless" class="virtual-x-left"></td>
|
|
146
146
|
<template v-if="fixedMode && headless">
|
|
147
147
|
<td v-for="col in virtualX_columnPart" :key="col.dataIndex" :style="cellStyleMap[TagType.TD].get(colKeyGen(col))"></td
|
|
148
148
|
></template>
|
|
@@ -163,7 +163,7 @@
|
|
|
163
163
|
@mouseover="e => onTrMouseOver(e, row)"
|
|
164
164
|
>
|
|
165
165
|
<!--这个td用于配合虚拟滚动的th对应,防止列错位-->
|
|
166
|
-
<td v-if="virtualX_on" class="virtual-x-left"
|
|
166
|
+
<td v-if="virtualX_on" class="virtual-x-left"></td>
|
|
167
167
|
<td
|
|
168
168
|
v-for="(col, colIndex) in virtualX_columnPart"
|
|
169
169
|
:key="col.dataIndex"
|
|
@@ -212,9 +212,9 @@
|
|
|
212
212
|
* [] 计算的高亮颜色,挂在数据源上对象上,若多个表格使用同一个数据源对象会有问题。需要深拷贝。(解决方案:获取组件uid)
|
|
213
213
|
* [] highlight-row 颜色不能恢复到active的颜色
|
|
214
214
|
*/
|
|
215
|
-
import { CSSProperties, computed, onMounted, ref, shallowRef, toRaw, watch } from 'vue';
|
|
215
|
+
import { CSSProperties, computed, nextTick, onMounted, ref, shallowRef, toRaw, watch } from 'vue';
|
|
216
216
|
import { DEFAULT_ROW_HEIGHT } from './const';
|
|
217
|
-
import { HighlightConfig, Order, SeqConfig, SortConfig, SortOption, SortState, StkTableColumn, TagType, UniqKeyProp } from './types/index';
|
|
217
|
+
import { HighlightConfig, Order, SeqConfig, SortConfig, SortOption, SortState, StkTableColumn, TagType, UniqKey, UniqKeyProp } from './types/index';
|
|
218
218
|
import { useAutoResize } from './useAutoResize';
|
|
219
219
|
import { useColResize } from './useColResize';
|
|
220
220
|
import { useFixedCol } from './useFixedCol';
|
|
@@ -320,6 +320,14 @@ const props = withDefaults(
|
|
|
320
320
|
highlightConfig?: HighlightConfig;
|
|
321
321
|
/** 序号列配置 */
|
|
322
322
|
seqConfig?: SeqConfig;
|
|
323
|
+
/**
|
|
324
|
+
* 固定头,固定列实现方式。
|
|
325
|
+
*
|
|
326
|
+
* relative:固定列只能放在props.columns的两侧。如果列宽会变动则谨慎使用。
|
|
327
|
+
*
|
|
328
|
+
* 低版本浏览器只能为'relative',
|
|
329
|
+
*/
|
|
330
|
+
cellFixedMode?: 'sticky' | 'relative';
|
|
323
331
|
}>(),
|
|
324
332
|
{
|
|
325
333
|
width: '',
|
|
@@ -360,6 +368,7 @@ const props = withDefaults(
|
|
|
360
368
|
hideHeaderTitle: false,
|
|
361
369
|
highlightConfig: () => ({}),
|
|
362
370
|
seqConfig: () => ({}),
|
|
371
|
+
cellFixedMode: 'sticky',
|
|
363
372
|
},
|
|
364
373
|
);
|
|
365
374
|
|
|
@@ -496,6 +505,18 @@ const tableHeaderLast = shallowRef<StkTableColumn<DT>[]>([]);
|
|
|
496
505
|
|
|
497
506
|
const dataSourceCopy = shallowRef<DT[]>([...props.dataSource]);
|
|
498
507
|
|
|
508
|
+
/**
|
|
509
|
+
* 列唯一键
|
|
510
|
+
* @param col
|
|
511
|
+
*/
|
|
512
|
+
const colKeyGen = computed(() => {
|
|
513
|
+
if (typeof props.colKey === 'function') {
|
|
514
|
+
return (col: StkTableColumn<DT>) => (props.colKey as (col: StkTableColumn<DT>) => string)(col);
|
|
515
|
+
} else {
|
|
516
|
+
return (col: StkTableColumn<DT>) => (col as any)[props.colKey as string];
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
|
|
499
520
|
/**高亮帧间隔
|
|
500
521
|
const highlightStepDuration = Highlight_Color_Change_Freq / 1000 + 's';*/
|
|
501
522
|
|
|
@@ -579,16 +600,17 @@ watch(
|
|
|
579
600
|
() => props.columns,
|
|
580
601
|
() => {
|
|
581
602
|
dealColumns();
|
|
582
|
-
initVirtualScrollX
|
|
603
|
+
nextTick(initVirtualScrollX);
|
|
583
604
|
},
|
|
584
605
|
);
|
|
585
606
|
watch(
|
|
586
607
|
() => props.virtualX,
|
|
587
|
-
() =>
|
|
608
|
+
() => {
|
|
609
|
+
dealColumns();
|
|
610
|
+
nextTick(initVirtualScrollX);
|
|
611
|
+
},
|
|
588
612
|
);
|
|
589
613
|
|
|
590
|
-
dealColumns();
|
|
591
|
-
|
|
592
614
|
watch(
|
|
593
615
|
() => props.dataSource,
|
|
594
616
|
val => {
|
|
@@ -618,6 +640,8 @@ watch(
|
|
|
618
640
|
|
|
619
641
|
watch(() => props.fixedColShadow, dealFixedColShadow);
|
|
620
642
|
|
|
643
|
+
dealColumns();
|
|
644
|
+
|
|
621
645
|
onMounted(() => {
|
|
622
646
|
initVirtualScroll();
|
|
623
647
|
updateFixedShadow();
|
|
@@ -717,21 +741,13 @@ function rowKeyGen(row: DT) {
|
|
|
717
741
|
return key;
|
|
718
742
|
}
|
|
719
743
|
|
|
720
|
-
/**
|
|
721
|
-
* 列唯一键
|
|
722
|
-
* @param col
|
|
723
|
-
*/
|
|
724
|
-
function colKeyGen(col: StkTableColumn<DT>) {
|
|
725
|
-
return typeof props.colKey === 'function' ? props.colKey(col) : (col as any)[props.colKey];
|
|
726
|
-
}
|
|
727
|
-
|
|
728
744
|
/** 单元格样式 */
|
|
729
745
|
const cellStyleMap = computed(() => {
|
|
730
746
|
const thMap = new Map();
|
|
731
747
|
const tdMap = new Map();
|
|
732
748
|
tableHeaders.value.forEach((cols, depth) => {
|
|
733
749
|
cols.forEach(col => {
|
|
734
|
-
const colKey = colKeyGen(col);
|
|
750
|
+
const colKey = colKeyGen.value(col);
|
|
735
751
|
const width = props.virtualX ? getCalculatedColWidth(col) + 'px' : transformWidthToStr(col.width);
|
|
736
752
|
const style: CSSProperties = {
|
|
737
753
|
width,
|
package/src/StkTable/style.less
CHANGED
|
@@ -116,28 +116,8 @@
|
|
|
116
116
|
background-image: var(--bg-border-right), var(--bg-border-bottom);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
thead {
|
|
120
|
-
|
|
121
|
-
&:first-child th {
|
|
122
|
-
background-image: var(--bg-border-top), var(--bg-border-right), var(--bg-border-bottom);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
&.virtual-x {
|
|
130
|
-
.virtual-x-left {
|
|
131
|
-
background: none;
|
|
132
|
-
pointer-events: none;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
.virtual-x-right {
|
|
136
|
-
padding: 0;
|
|
137
|
-
background: none;
|
|
138
|
-
pointer-events: none;
|
|
139
|
-
}
|
|
140
|
-
|
|
119
|
+
thead tr:first-child th {
|
|
120
|
+
background-image: var(--bg-border-top), var(--bg-border-right), var(--bg-border-bottom);
|
|
141
121
|
}
|
|
142
122
|
}
|
|
143
123
|
|
|
@@ -191,15 +171,13 @@
|
|
|
191
171
|
max-height: var(--header-row-height);
|
|
192
172
|
}
|
|
193
173
|
|
|
194
|
-
tbody {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
overflow: hidden;
|
|
202
|
-
}
|
|
174
|
+
tbody td {
|
|
175
|
+
height: var(--row-height);
|
|
176
|
+
line-height: 1;
|
|
177
|
+
|
|
178
|
+
.table-cell-wrapper {
|
|
179
|
+
max-height: var(--row-height);
|
|
180
|
+
overflow: hidden;
|
|
203
181
|
}
|
|
204
182
|
}
|
|
205
183
|
|
|
@@ -208,12 +186,6 @@
|
|
|
208
186
|
}
|
|
209
187
|
}
|
|
210
188
|
|
|
211
|
-
&.virtual-x {
|
|
212
|
-
.virtual-x-left {
|
|
213
|
-
padding: 0;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
189
|
th,
|
|
218
190
|
td {
|
|
219
191
|
z-index: 1;
|
|
@@ -294,6 +266,13 @@
|
|
|
294
266
|
}
|
|
295
267
|
}
|
|
296
268
|
|
|
269
|
+
.virtual-x-left,
|
|
270
|
+
.virtual-x-right {
|
|
271
|
+
padding: 0;
|
|
272
|
+
background: none;
|
|
273
|
+
pointer-events: none;
|
|
274
|
+
}
|
|
275
|
+
|
|
297
276
|
|
|
298
277
|
/** 列宽调整指示器 */
|
|
299
278
|
.column-resize-indicator {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Ref, ShallowRef, onBeforeUnmount, onMounted, ref } from 'vue';
|
|
2
|
-
import { StkTableColumn } from './types';
|
|
1
|
+
import { ComputedRef, Ref, ShallowRef, onBeforeUnmount, onMounted, ref } from 'vue';
|
|
2
|
+
import { StkTableColumn, UniqKey } from './types';
|
|
3
3
|
import { getCalculatedColWidth } from './utils';
|
|
4
4
|
|
|
5
5
|
type ColResizeState<DT extends Record<string, any>> = {
|
|
@@ -21,7 +21,7 @@ type Params<DT extends Record<string, any>> = {
|
|
|
21
21
|
tableContainerRef: Ref<HTMLElement | undefined>;
|
|
22
22
|
tableHeaderLast: ShallowRef<StkTableColumn<DT>[]>;
|
|
23
23
|
colResizeIndicatorRef: Ref<HTMLElement | undefined>;
|
|
24
|
-
colKeyGen: (p: any) =>
|
|
24
|
+
colKeyGen: ComputedRef<(p: any) => UniqKey>;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
/** 列宽拖动 */
|
|
@@ -78,7 +78,7 @@ export function useColResize<DT extends Record<string, any>>({
|
|
|
78
78
|
const { scrollLeft, scrollTop } = tableContainerRef.value;
|
|
79
79
|
const { left } = tableContainerRef.value.getBoundingClientRect();
|
|
80
80
|
/** 列下标 */
|
|
81
|
-
let colIndex = tableHeaderLast.value.findIndex(it => colKeyGen(it) === colKeyGen(col));
|
|
81
|
+
let colIndex = tableHeaderLast.value.findIndex(it => colKeyGen.value(it) === colKeyGen.value(col));
|
|
82
82
|
if (isPrev) {
|
|
83
83
|
// 上一列
|
|
84
84
|
colIndex -= 1;
|
|
@@ -139,7 +139,7 @@ export function useColResize<DT extends Record<string, any>>({
|
|
|
139
139
|
let width = getCalculatedColWidth(lastCol) + moveX;
|
|
140
140
|
if (width < props.colMinWidth) width = props.colMinWidth;
|
|
141
141
|
|
|
142
|
-
const curCol = tableHeaderLast.value.find(it => colKeyGen(it) === colKeyGen(lastCol));
|
|
142
|
+
const curCol = tableHeaderLast.value.find(it => colKeyGen.value(it) === colKeyGen.value(lastCol));
|
|
143
143
|
if (!curCol) return;
|
|
144
144
|
curCol.width = width + 'px';
|
|
145
145
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { computed, ref, Ref, ShallowRef, shallowRef } from 'vue';
|
|
2
|
-
import { StkTableColumn } from './types';
|
|
1
|
+
import { computed, ComputedRef, ref, Ref, ShallowRef, shallowRef } from 'vue';
|
|
2
|
+
import { StkTableColumn, UniqKey } from './types';
|
|
3
3
|
|
|
4
4
|
type Params<T extends Record<string, any>> = {
|
|
5
5
|
props: any;
|
|
6
|
-
colKeyGen: (col: StkTableColumn<T>) =>
|
|
6
|
+
colKeyGen: ComputedRef<(col: StkTableColumn<T>) => UniqKey>;
|
|
7
7
|
tableHeaders: ShallowRef<StkTableColumn<T>[][]>;
|
|
8
8
|
tableHeaderLast: ShallowRef<StkTableColumn<T>[]>;
|
|
9
9
|
tableContainerRef: Ref<HTMLDivElement | undefined>;
|
|
@@ -42,7 +42,7 @@ export function useFixedCol<DT extends Record<string, any>>({ props, colKeyGen,
|
|
|
42
42
|
['fixed-cell--' + col.fixed]: col.fixed,
|
|
43
43
|
'fixed-cell--shadow': showShadow,
|
|
44
44
|
};
|
|
45
|
-
colMap.set(colKeyGen(col), classObj);
|
|
45
|
+
colMap.set(colKeyGen.value(col), classObj);
|
|
46
46
|
});
|
|
47
47
|
});
|
|
48
48
|
return colMap;
|
|
@@ -75,19 +75,39 @@ export function useFixedStyle<DT extends Record<string, any>>({
|
|
|
75
75
|
const { fixed } = col;
|
|
76
76
|
if (tagType === TagType.TD && !fixed) return null;
|
|
77
77
|
|
|
78
|
-
const isFixedLeft = fixed === 'left';
|
|
79
78
|
const style: CSSProperties = {};
|
|
80
79
|
const { colKeyStore, refStore } = fixedColumnsPositionStore.value;
|
|
81
80
|
|
|
81
|
+
/** 是否是relative模式完成固定列 */
|
|
82
|
+
let isRelativeMode = true;
|
|
83
|
+
if (props.cellFixedMode === 'sticky') {
|
|
84
|
+
isRelativeMode = false;
|
|
85
|
+
}
|
|
86
|
+
|
|
82
87
|
if (IS_LEGACY_MODE) {
|
|
88
|
+
// 低版本浏览器只能为固定列设置position: sticky
|
|
89
|
+
isRelativeMode = true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const { scrollLeft, scrollWidth, offsetLeft, containerWidth } = virtualScrollX.value;
|
|
93
|
+
const scrollRight = scrollWidth - containerWidth - scrollLeft;
|
|
94
|
+
|
|
95
|
+
if (virtualScrollX.value.scrollLeft === 0 && fixed === 'left' && tagType === TagType.TD) {
|
|
96
|
+
// 滚动条在最左侧时,左侧固定列不需要,防止分层
|
|
97
|
+
style.position = void 0;
|
|
98
|
+
} else if (scrollRight === 0 && fixed === 'right' && tagType === TagType.TD) {
|
|
99
|
+
// 滚动条在最右侧时,右侧固定列不需要,防止分层
|
|
100
|
+
style.position = void 0;
|
|
101
|
+
} else if (isRelativeMode) {
|
|
83
102
|
style.position = 'relative';
|
|
84
103
|
} else {
|
|
85
104
|
style.position = 'sticky';
|
|
86
105
|
}
|
|
87
106
|
|
|
107
|
+
const isFixedLeft = fixed === 'left';
|
|
88
108
|
if (tagType === TagType.TH) {
|
|
89
109
|
// TH
|
|
90
|
-
if (
|
|
110
|
+
if (isRelativeMode) {
|
|
91
111
|
style.top = virtualScroll.value.scrollTop + 'px';
|
|
92
112
|
} else {
|
|
93
113
|
style.top = depth * props.rowHeight + 'px';
|
|
@@ -95,17 +115,18 @@ export function useFixedStyle<DT extends Record<string, any>>({
|
|
|
95
115
|
style.zIndex = isFixedLeft ? '3' : '2'; // 保证固定列高于其他单元格
|
|
96
116
|
} else {
|
|
97
117
|
// TD
|
|
98
|
-
|
|
118
|
+
if (isFixedLeft) {
|
|
119
|
+
style.zIndex = '2';
|
|
120
|
+
}
|
|
99
121
|
}
|
|
100
122
|
|
|
101
123
|
if (fixed === 'left' || fixed === 'right') {
|
|
102
|
-
if (
|
|
124
|
+
if (isRelativeMode) {
|
|
103
125
|
if (isFixedLeft) {
|
|
104
|
-
|
|
105
|
-
else style.left = virtualScrollX.value.scrollLeft + 'px';
|
|
126
|
+
style.left = scrollLeft - (virtualX_on.value ? offsetLeft : 0) + 'px';
|
|
106
127
|
} else {
|
|
107
|
-
//
|
|
108
|
-
style.right =
|
|
128
|
+
// fixed right
|
|
129
|
+
style.right = Math.max(scrollRight - (virtualX_on.value ? virtualX_offsetRight.value : 0), 0) + 'px';
|
|
109
130
|
}
|
|
110
131
|
} else {
|
|
111
132
|
const lr = (col.dataIndex ? colKeyStore[col.dataIndex] : refStore.get(col)) + 'px';
|
|
@@ -30,8 +30,10 @@ export type VirtualScrollStore = {
|
|
|
30
30
|
};
|
|
31
31
|
/** 暂存横向虚拟滚动的数据 */
|
|
32
32
|
export type VirtualScrollXStore = {
|
|
33
|
-
/**
|
|
33
|
+
/** 父容器宽度 */
|
|
34
34
|
containerWidth: number;
|
|
35
|
+
/** 滚动容器的宽度 */
|
|
36
|
+
scrollWidth: number;
|
|
35
37
|
/** 开始位置 */
|
|
36
38
|
startIndex: number;
|
|
37
39
|
/** 结束始位置 */
|
|
@@ -69,6 +71,7 @@ export function useVirtualScroll<DT extends Record<string, any>>({
|
|
|
69
71
|
|
|
70
72
|
const virtualScrollX = ref<VirtualScrollXStore>({
|
|
71
73
|
containerWidth: 0,
|
|
74
|
+
scrollWidth: 0,
|
|
72
75
|
startIndex: 0,
|
|
73
76
|
endIndex: 0,
|
|
74
77
|
offsetLeft: 0,
|
|
@@ -162,10 +165,9 @@ export function useVirtualScroll<DT extends Record<string, any>>({
|
|
|
162
165
|
}
|
|
163
166
|
|
|
164
167
|
function initVirtualScrollX() {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
virtualScrollX.value.containerWidth = offsetWidth || DEFAULT_TABLE_WIDTH;
|
|
168
|
+
const { clientWidth, scrollLeft, scrollWidth } = tableContainerRef.value || {};
|
|
169
|
+
virtualScrollX.value.containerWidth = clientWidth || DEFAULT_TABLE_WIDTH;
|
|
170
|
+
virtualScrollX.value.scrollWidth = scrollWidth || DEFAULT_TABLE_WIDTH;
|
|
169
171
|
updateVirtualScrollX(scrollLeft);
|
|
170
172
|
}
|
|
171
173
|
/**
|
|
@@ -237,6 +239,7 @@ export function useVirtualScroll<DT extends Record<string, any>>({
|
|
|
237
239
|
|
|
238
240
|
/** 通过横向滚动条位置,计算横向虚拟滚动的参数 */
|
|
239
241
|
function updateVirtualScrollX(sLeft = 0) {
|
|
242
|
+
if (!props.virtualX) return;
|
|
240
243
|
const headerLength = tableHeaderLast.value?.length;
|
|
241
244
|
const { scrollLeft } = virtualScrollX.value;
|
|
242
245
|
if (!headerLength) return;
|