stk-table-vue 0.3.3 → 0.3.5

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 CHANGED
@@ -16,7 +16,7 @@ repo:
16
16
  - [x] 虚拟滚动默认通过js计算行高亮背景色,可通过 `useCss` 设置为css @keyframe实现 。
17
17
  - [x] 支持配置高亮参数(持续时间,颜色,频率(虚拟滚动))。(`v0.2.9`)
18
18
  - [x] `setHighlightDimRow`/`setHighlightCellRow`支持自定义高亮css类名。(`v0.2.9`)
19
- - [x] 使用 `Web Animations API` 实现高亮。
19
+ - [x] 使用 `Web Animations API` 实现高亮。(`v0.3.4` 变更为默认值)
20
20
  * [x] 虚拟滚动。
21
21
  - [x] 纵向。
22
22
  - [x] 横向(必须设置列宽)。
@@ -223,7 +223,7 @@ export type StkProps = {
223
223
  highlightConfig?: {
224
224
  /** 高亮持续时间(s) */
225
225
  duration?: number;
226
- /** 高亮帧率(虚拟滚动生效) */
226
+ /** 高亮帧率*/
227
227
  fps?: number;
228
228
  };
229
229
  /** 序号列配置 */
@@ -549,13 +549,23 @@ export type SortConfig<T extends Record<string, any>> = {
549
549
  ### 鼠标悬浮表头时,不展示title
550
550
  * 将 `StkTableColumn` 中的 `title` 字段置为 "" 空字符串。这样th中就没有title了。
551
551
  * 使用 `StkTableColumn` 中的 `customHeaderCell` 属性中,自定义表头渲染。
552
- ### 高亮性能
553
- * 在虚拟滚动下高亮强制使用css @keyframes 实现动画。`setHighlightDimRow`/`setHighlightCellRow` 最后一个参数传入 `{method: 'css'}` 即可。(滚动后动画会中断)
554
- * 指定 `{method:'animation'}` 在虚拟滚动下使用animation api实现动画。好处是动画流畅,且滚动后动画不中断。
552
+
553
+ ## Performance optimization
554
+ ### highlight
555
555
  * 配置 `props.highlightConfig.fps` 指定高亮帧率。降低帧率有利于性能。
556
- ### 性能
557
- * 配置 `props.cellFixedMode` 为 `relative` 时,将使用相对定位实现固定列与固定表头,相较于`sticky`的实现,渲染合成层更少,性能更好。
556
+ ### relative fixed
557
+ * 配置 `props.cellFixedMode` 为 `relative` 时,将使用相对定位实现固定列与固定表头,相较于`sticky`的实现,渲染合成层更少。
558
558
  * 问题:若开启了纵向虚拟滚动,不开启横向虚拟滚动,且不设置某些列宽时。如果纵向滚动导致某些列宽变化,则会导致右侧固定列计算错误。
559
+ ### tr 分层
560
+ * 通过css选择器将 stk-table tbody tr 配置 `transform:translateZ(0)` 对每行 tr 进行分层。对性能有帮助。
561
+ - 提升合成层可能导致黑底红字字体颜色发生变化。
562
+ - 以下情况尝试开启此功能。
563
+ - 在 `customCell` 较多且复杂时。
564
+ - 大量 highlight 动画时。
559
565
 
560
566
  ## Other
561
567
  * `$*$` 兼容注释
568
+
569
+
570
+ ### Planed removal APi
571
+ * `setHighlightDimRow` 中的 `method="js"`。观察animation Api 是否足够满足使用场景。若足够满足计划在后期移除,并且可以移除 `d3-interpolate` 依赖。
@@ -186,13 +186,13 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
186
186
  /** 设置高亮渐暗单元格 */
187
187
  setHighlightDimCell: (rowKeyValue: string, dataIndex: string, option?: {
188
188
  className?: string | undefined;
189
- method?: "css" | "animation" | undefined;
189
+ method?: "animation" | "css" | undefined;
190
190
  keyframe?: Keyframe[] | PropertyIndexedKeyframes | null | undefined;
191
191
  duration?: number | undefined;
192
192
  }) => void;
193
193
  /** 设置高亮渐暗行 */
194
194
  setHighlightDimRow: (rowKeyValues: UniqKey[], option?: {
195
- method?: "css" | "animation" | "js" | undefined;
195
+ method?: "animation" | "css" | "js" | undefined;
196
196
  useCss?: boolean | undefined;
197
197
  className?: string | undefined;
198
198
  keyframe?: Keyframe[] | PropertyIndexedKeyframes | null | undefined;
@@ -8,7 +8,10 @@ type Sorter<T> = boolean | ((data: T[], option: {
8
8
  export type CustomCellFunc<T extends Record<string, any>> = (props: {
9
9
  row: T;
10
10
  col: StkTableColumn<T>;
11
+ /** row[col.dataIndex] 的值 */
11
12
  cellValue: any;
13
+ rowIndex: number;
14
+ colIndex: number;
12
15
  }) => VNode;
13
16
  export type CustomHeaderCellFunc<T extends Record<string, any>> = (props: {
14
17
  col: StkTableColumn<T>;
@@ -9,9 +9,9 @@ type Params = {
9
9
  * 高亮单元格,行
10
10
  */
11
11
  export declare function useHighlight({ props, stkTableId, tableContainerRef }: Params): {
12
- highlightSteps: number;
12
+ highlightSteps: number | null;
13
13
  setHighlightDimRow: (rowKeyValues: UniqKey[], option?: {
14
- method?: 'css' | 'animation' | 'js';
14
+ method?: 'animation' | 'css' | 'js';
15
15
  /** @deprecated 请使用method */
16
16
  useCss?: boolean;
17
17
  className?: string;
@@ -20,7 +20,7 @@ export declare function useHighlight({ props, stkTableId, tableContainerRef }: P
20
20
  }) => void;
21
21
  setHighlightDimCell: (rowKeyValue: string, dataIndex: string, option?: {
22
22
  className?: string;
23
- method?: 'css' | 'animation';
23
+ method?: 'animation' | 'css';
24
24
  keyframe?: Parameters<Animatable['animate']>['0'];
25
25
  duration?: number;
26
26
  }) => void;
@@ -510,13 +510,13 @@ function useFixedStyle({
510
510
  }
511
511
  function useHighlight({ props, stkTableId, tableContainerRef }) {
512
512
  const config = props.highlightConfig;
513
- const highlightDuration = config.duration ? config.duration * 1e3 : HIGHLIGHT_DURATION;
514
- const highlightFrequency = config.fps ? 1e3 / config.fps : HIGHLIGHT_FREQ;
515
513
  const highlightColor = {
516
514
  light: HIGHLIGHT_COLOR.light,
517
515
  dark: HIGHLIGHT_COLOR.dark
518
516
  };
519
- const highlightSteps = highlightDuration / highlightFrequency;
517
+ const highlightDuration = config.duration ? config.duration * 1e3 : HIGHLIGHT_DURATION;
518
+ const highlightFrequency = config.fps && config.fps > 0 ? 1e3 / config.fps : null;
519
+ const highlightSteps = highlightFrequency ? Math.round(highlightDuration / highlightFrequency) : null;
520
520
  const highlightFrom = computed(() => highlightColor[props.theme].from);
521
521
  const highlightTo = computed(() => highlightColor[props.theme].to);
522
522
  const highlightInter = computed(() => interpolateRgb(highlightFrom.value, highlightTo.value));
@@ -526,6 +526,13 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
526
526
  let calcHighlightDimLoopAnimation = false;
527
527
  const highlightDimRowsTimeout = /* @__PURE__ */ new Map();
528
528
  const highlightDimCellsTimeout = /* @__PURE__ */ new Map();
529
+ const defaultHighlightDimOption = (() => {
530
+ const keyframe = { backgroundColor: [highlightFrom.value, highlightTo.value] };
531
+ if (highlightSteps) {
532
+ keyframe.easing = `steps(${highlightSteps})`;
533
+ }
534
+ return { duration: highlightDuration, keyframe };
535
+ })();
529
536
  function calcRowHighlightLoop() {
530
537
  if (calcHighlightDimLoopAnimation)
531
538
  return;
@@ -577,20 +584,16 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
577
584
  calcHighlightDimLoopJs = false;
578
585
  highlightDimRowsJs.clear();
579
586
  }
580
- }, highlightFrequency);
587
+ }, highlightFrequency || HIGHLIGHT_FREQ);
581
588
  };
582
589
  recursion();
583
590
  }
584
- const defaultHighlightDimOption = {
585
- keyframe: [{ backgroundColor: highlightFrom.value }, { backgroundColor: highlightTo.value }],
586
- duration: highlightDuration
587
- };
588
591
  function setHighlightDimCell(rowKeyValue, dataIndex, option = {}) {
589
592
  var _a;
590
593
  const cellEl = (_a = tableContainerRef.value) == null ? void 0 : _a.querySelector(`[data-row-key="${rowKeyValue}"]>[data-index="${dataIndex}"]`);
591
594
  const { className, method, duration, keyframe } = {
592
595
  className: HIGHLIGHT_CELL_CLASS,
593
- method: "css",
596
+ method: "animation",
594
597
  ...defaultHighlightDimOption,
595
598
  ...option
596
599
  };
@@ -607,7 +610,7 @@ function useHighlight({ props, stkTableId, tableContainerRef }) {
607
610
  rowKeyValues = [rowKeyValues];
608
611
  const { className, method, useCss, keyframe, duration } = {
609
612
  className: HIGHLIGHT_ROW_CLASS,
610
- method: props.virtual ? "js" : "css",
613
+ method: "animation",
611
614
  ...defaultHighlightDimOption,
612
615
  ...option
613
616
  };
@@ -906,16 +909,15 @@ function useVirtualScroll({
906
909
  return width;
907
910
  });
908
911
  function initVirtualScrollY(height) {
912
+ if (height !== void 0 && typeof height !== "number") {
913
+ console.warn("initVirtualScrollY: height must be a number");
914
+ height = 0;
915
+ }
909
916
  if (!virtual_on.value)
910
917
  return;
911
918
  const { offsetHeight, scrollTop } = tableContainerRef.value || {};
912
919
  const { rowHeight } = virtualScroll.value;
913
- let containerHeight;
914
- if (typeof height === "number") {
915
- containerHeight = height;
916
- } else {
917
- containerHeight = offsetHeight || DEFAULT_TABLE_HEIGHT;
918
- }
920
+ const containerHeight = height || offsetHeight || DEFAULT_TABLE_HEIGHT;
919
921
  const { headless, headerRowHeight } = props;
920
922
  let pageSize = Math.ceil(containerHeight / rowHeight);
921
923
  if (!headless) {
@@ -942,17 +944,12 @@ function useVirtualScroll({
942
944
  if (!virtual_on.value)
943
945
  return;
944
946
  let startIndex = Math.floor(sTop / rowHeight);
945
- if (props.stripe) {
946
- startIndex -= 1;
947
- }
948
947
  if (startIndex < 0) {
949
948
  startIndex = 0;
950
949
  }
951
950
  if (props.stripe && startIndex !== 0) {
952
951
  const scrollRows = Math.abs(oldStartIndex - startIndex);
953
- if (scrollRows < 2) {
954
- return;
955
- } else if (scrollRows % 2) {
952
+ if (scrollRows % 2) {
956
953
  startIndex -= 1;
957
954
  }
958
955
  }
@@ -984,17 +981,18 @@ function useVirtualScroll({
984
981
  if (!props.virtualX)
985
982
  return;
986
983
  const headerLength = (_a = tableHeaderLast.value) == null ? void 0 : _a.length;
987
- const { scrollLeft } = virtualScrollX.value;
988
984
  if (!headerLength)
989
985
  return;
986
+ const { scrollLeft } = virtualScrollX.value;
990
987
  let startIndex = 0;
991
988
  let offsetLeft = 0;
992
989
  let colWidthSum = 0;
993
990
  let leftColWidthSum = 0;
991
+ let leftFirstColRestWidth = 0;
994
992
  for (let colIndex = 0; colIndex < headerLength; colIndex++) {
995
- startIndex++;
996
993
  const col = tableHeaderLast.value[colIndex];
997
994
  const colWidth = getCalculatedColWidth(col);
995
+ startIndex++;
998
996
  if (col.fixed === "left") {
999
997
  leftColWidthSum += colWidth;
1000
998
  continue;
@@ -1003,10 +1001,11 @@ function useVirtualScroll({
1003
1001
  if (colWidthSum >= sLeft) {
1004
1002
  offsetLeft = colWidthSum - colWidth;
1005
1003
  startIndex--;
1004
+ leftFirstColRestWidth = colWidthSum - sLeft;
1006
1005
  break;
1007
1006
  }
1008
1007
  }
1009
- colWidthSum = 0;
1008
+ colWidthSum = leftFirstColRestWidth;
1010
1009
  const containerWidth = virtualScrollX.value.containerWidth - leftColWidthSum;
1011
1010
  let endIndex = headerLength;
1012
1011
  for (let colIndex = startIndex + 1; colIndex < headerLength; colIndex++) {
@@ -1570,16 +1569,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1570
1569
  "text-overflow": props.showOverflow,
1571
1570
  "header-text-overflow": props.showHeaderOverflow
1572
1571
  }]),
1573
- style: normalizeStyle([
1574
- _ctx.virtual && {
1575
- "--row-height": unref(virtualScroll).rowHeight + "px",
1576
- "--header-row-height": (props.headerRowHeight || props.rowHeight) + "px"
1577
- },
1578
- {
1579
- "--highlight-duration": props.highlightConfig.duration && props.highlightConfig.duration + "s",
1580
- "--highlight-timing-function": unref(highlightSteps) ? `steps(${unref(highlightSteps)})` : ""
1581
- }
1582
- ]),
1572
+ style: normalizeStyle({
1573
+ "--row-height": unref(virtualScroll).rowHeight + "px",
1574
+ "--header-row-height": (props.headerRowHeight || props.rowHeight) + "px",
1575
+ "--highlight-duration": props.highlightConfig.duration && props.highlightConfig.duration + "s",
1576
+ "--highlight-timing-function": unref(highlightSteps) ? `steps(${unref(highlightSteps)})` : ""
1577
+ }),
1583
1578
  onScroll: onTableScroll,
1584
1579
  onWheel: onTableWheel
1585
1580
  }, [
@@ -1715,10 +1710,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1715
1710
  key: 0,
1716
1711
  col,
1717
1712
  row,
1718
- "row-index": rowIndex,
1719
- "col-index": colIndex,
1720
- "cell-value": row[col.dataIndex]
1721
- }, null, 8, ["col", "row", "row-index", "col-index", "cell-value"])) : (openBlock(), createElementBlock("div", {
1713
+ rowIndex,
1714
+ colIndex,
1715
+ cellValue: row[col.dataIndex]
1716
+ }, null, 8, ["col", "row", "rowIndex", "colIndex", "cellValue"])) : (openBlock(), createElementBlock("div", {
1722
1717
  key: 1,
1723
1718
  class: "table-cell-wrapper",
1724
1719
  title: !col.type ? row[col.dataIndex] : ""
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "stk-table-vue",
3
- "version": "0.3.3",
4
- "description": "Simple realtime virtual table for vue3&vue2.7",
3
+ "version": "0.3.5",
4
+ "description": "Simple realtime virtual table for vue3 and vue2.7",
5
5
  "main": "./lib/stk-table-vue.js",
6
6
  "types": "./lib/src/StkTable/index.d.ts",
7
7
  "packageManager": "pnpm@8.14.3",
@@ -17,8 +17,13 @@
17
17
  "keywords": [
18
18
  "virtual table",
19
19
  "vue",
20
+ "vue2",
21
+ "vue3",
20
22
  "highlight",
21
- "sticky"
23
+ "sticky",
24
+ "virtual",
25
+ "table",
26
+ "list"
22
27
  ],
23
28
  "files": [
24
29
  "lib",
@@ -27,7 +32,7 @@
27
32
  "author": "japlus",
28
33
  "repository": {
29
34
  "type": "git",
30
- "url": "https://gitee.com/japlus/stk-table-vue"
35
+ "url": "https://github.com/ja-plus/stk-table-vue"
31
36
  },
32
37
  "license": "MIT",
33
38
  "devDependencies": {
@@ -18,16 +18,12 @@
18
18
  'text-overflow': props.showOverflow,
19
19
  'header-text-overflow': props.showHeaderOverflow,
20
20
  }"
21
- :style="[
22
- virtual && {
23
- '--row-height': virtualScroll.rowHeight + 'px',
24
- '--header-row-height': (props.headerRowHeight || props.rowHeight) + 'px',
25
- },
26
- {
27
- '--highlight-duration': props.highlightConfig.duration && props.highlightConfig.duration + 's',
28
- '--highlight-timing-function': highlightSteps ? `steps(${highlightSteps})` : '',
29
- },
30
- ]"
21
+ :style="{
22
+ '--row-height': virtualScroll.rowHeight + 'px',
23
+ '--header-row-height': (props.headerRowHeight || props.rowHeight) + 'px',
24
+ '--highlight-duration': props.highlightConfig.duration && props.highlightConfig.duration + 's',
25
+ '--highlight-timing-function': highlightSteps ? `steps(${highlightSteps})` : '',
26
+ }"
31
27
  @scroll="onTableScroll"
32
28
  @wheel="onTableWheel"
33
29
  >
@@ -180,9 +176,9 @@
180
176
  v-if="col.customCell"
181
177
  :col="col"
182
178
  :row="row"
183
- :row-index="rowIndex"
184
- :col-index="colIndex"
185
- :cell-value="row[col.dataIndex]"
179
+ :rowIndex="rowIndex"
180
+ :colIndex="colIndex"
181
+ :cellValue="row[col.dataIndex]"
186
182
  />
187
183
  <div v-else class="table-cell-wrapper" :title="!col.type ? row[col.dataIndex] : ''">
188
184
  <template v-if="col.type === 'seq'">
@@ -11,6 +11,7 @@ export const HIGHLIGHT_COLOR = {
11
11
  };
12
12
  /** 高亮持续时间 */
13
13
  export const HIGHLIGHT_DURATION = 2000;
14
+
14
15
  /** 高亮变更频率 */
15
16
  export const HIGHLIGHT_FREQ = 1000 / 30;
16
17
 
@@ -5,7 +5,15 @@ export type Order = null | 'asc' | 'desc';
5
5
 
6
6
  type Sorter<T> = boolean | ((data: T[], option: { order: Order; column: any }) => T[]);
7
7
 
8
- export type CustomCellFunc<T extends Record<string, any>> = (props: { row: T; col: StkTableColumn<T>; cellValue: any }) => VNode;
8
+ export type CustomCellFunc<T extends Record<string, any>> = (props: {
9
+ row: T;
10
+ col: StkTableColumn<T>;
11
+ /** row[col.dataIndex] 的值 */
12
+ cellValue: any;
13
+ rowIndex: number;
14
+ colIndex: number;
15
+ }) => VNode;
16
+
9
17
  export type CustomHeaderCellFunc<T extends Record<string, any>> = (props: { col: StkTableColumn<T> }) => VNode;
10
18
 
11
19
  /** 表格列配置 */
@@ -26,18 +26,17 @@ type HighlightDimRowStore = {
26
26
  export function useHighlight({ props, stkTableId, tableContainerRef }: Params) {
27
27
  const config: HighlightConfig = props.highlightConfig;
28
28
 
29
- /** 持续时间 */
30
- const highlightDuration = config.duration ? config.duration * 1000 : HIGHLIGHT_DURATION;
31
- /** 高亮频率(仅虚拟滚动生效) */
32
- const highlightFrequency = config.fps ? 1000 / config.fps : HIGHLIGHT_FREQ;
33
29
  /** 高亮颜色 */
34
30
  const highlightColor = {
35
31
  light: HIGHLIGHT_COLOR.light,
36
32
  dark: HIGHLIGHT_COLOR.dark,
37
33
  };
38
-
39
- /** css 高亮的次数,用于css animation steps() */
40
- const highlightSteps = highlightDuration / highlightFrequency;
34
+ /** 持续时间 */
35
+ const highlightDuration = config.duration ? config.duration * 1000 : HIGHLIGHT_DURATION;
36
+ /** 高亮频率*/
37
+ const highlightFrequency = config.fps && config.fps > 0 ? 1000 / config.fps : null;
38
+ /** 高亮帧数(非帧率),用于 timing-function: steps() */
39
+ const highlightSteps = highlightFrequency ? Math.round(highlightDuration / highlightFrequency) : null;
41
40
  /** 高亮开始 */
42
41
  const highlightFrom = computed(() => highlightColor[props.theme as 'light' | 'dark'].from);
43
42
  /** 高亮结束 */
@@ -66,6 +65,15 @@ export function useHighlight({ props, stkTableId, tableContainerRef }: Params) {
66
65
  /** 高亮后渐暗的单元格定时器 */
67
66
  const highlightDimCellsTimeout = new Map();
68
67
 
68
+ /** 高亮函数的默认参数 */
69
+ const defaultHighlightDimOption = (() => {
70
+ const keyframe: PropertyIndexedKeyframes = { backgroundColor: [highlightFrom.value, highlightTo.value] };
71
+ if (highlightSteps) {
72
+ keyframe.easing = `steps(${highlightSteps})`;
73
+ }
74
+ return { duration: highlightDuration, keyframe };
75
+ })();
76
+
69
77
  /**
70
78
  * 计算高亮渐暗颜色的循环
71
79
  */
@@ -130,22 +138,16 @@ export function useHighlight({ props, stkTableId, tableContainerRef }: Params) {
130
138
  calcHighlightDimLoopJs = false;
131
139
  highlightDimRowsJs.clear(); // TODO: 是否需要 清除
132
140
  }
133
- }, highlightFrequency);
141
+ }, highlightFrequency || HIGHLIGHT_FREQ);
134
142
  };
135
143
  recursion();
136
144
  }
137
145
 
138
- /** 高亮函数的默认参数 */
139
- const defaultHighlightDimOption = {
140
- keyframe: [{ backgroundColor: highlightFrom.value }, { backgroundColor: highlightTo.value }],
141
- duration: highlightDuration,
142
- };
143
-
144
146
  /**
145
- * 高亮一个单元格
147
+ * 高亮一个单元格。暂不支持虚拟滚动高亮状态记忆。
146
148
  * @param rowKeyValue 一行的key
147
149
  * @param dataIndex 列key
148
- * @param options.method css-使用css渲染,animation-使用animation api。默认css;
150
+ * @param options.method css-使用css渲染,animation-使用animation api。默认animation;
149
151
  * @param option.className 自定义css动画的class。
150
152
  * @param option.keyframe 同Keyframe https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Animations_API/Keyframe_Formats
151
153
  * @param option.duration 动画时长。method='css'状态下,用于移除class,如果传入了className则需要与自定义的动画时间一致。
@@ -153,13 +155,12 @@ export function useHighlight({ props, stkTableId, tableContainerRef }: Params) {
153
155
  function setHighlightDimCell(
154
156
  rowKeyValue: string,
155
157
  dataIndex: string,
156
- option: { className?: string; method?: 'css' | 'animation'; keyframe?: Parameters<Animatable['animate']>['0']; duration?: number } = {},
158
+ option: { className?: string; method?: 'animation' | 'css'; keyframe?: Parameters<Animatable['animate']>['0']; duration?: number } = {},
157
159
  ) {
158
- // TODO: 支持动态计算高亮颜色。不易实现。需记录每一个单元格的颜色情况。
159
160
  const cellEl = tableContainerRef.value?.querySelector<HTMLElement>(`[data-row-key="${rowKeyValue}"]>[data-index="${dataIndex}"]`);
160
161
  const { className, method, duration, keyframe } = {
161
162
  className: HIGHLIGHT_CELL_CLASS,
162
- method: 'css',
163
+ method: 'animation',
163
164
  ...defaultHighlightDimOption,
164
165
  ...option,
165
166
  };
@@ -174,15 +175,15 @@ export function useHighlight({ props, stkTableId, tableContainerRef }: Params) {
174
175
  /**
175
176
  * 高亮一行
176
177
  * @param rowKeyValues 行唯一键的数组
177
- * @param option.method css-使用css渲染,animation-使用animation api,js-使用js计算颜色
178
+ * @param option.method css-使用css渲染,animation-使用animation api,js-使用js计算颜色。默认animation
178
179
  * @param option.className 自定义css动画的class。
179
- * @param option.keyframe 同Keyframe,无法控制帧率。 https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Animations_API/Keyframe_Formats
180
+ * @param option.keyframe 同Keyframe https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Animations_API/Keyframe_Formats
180
181
  * @param option.duration 动画时长。method='css'状态下,用于移除class,如果传入了className则需要与自定义的动画时间一致。。
181
182
  */
182
183
  function setHighlightDimRow(
183
184
  rowKeyValues: UniqKey[],
184
185
  option: {
185
- method?: 'css' | 'animation' | 'js';
186
+ method?: 'animation' | 'css' | 'js';
186
187
  /** @deprecated 请使用method */
187
188
  useCss?: boolean;
188
189
  className?: string;
@@ -193,7 +194,7 @@ export function useHighlight({ props, stkTableId, tableContainerRef }: Params) {
193
194
  if (!Array.isArray(rowKeyValues)) rowKeyValues = [rowKeyValues];
194
195
  const { className, method, useCss, keyframe, duration } = {
195
196
  className: HIGHLIGHT_ROW_CLASS,
196
- method: props.virtual ? 'js' : 'css',
197
+ method: 'animation',
197
198
  ...defaultHighlightDimOption,
198
199
  ...option,
199
200
  };
@@ -234,7 +235,7 @@ export function useHighlight({ props, stkTableId, tableContainerRef }: Params) {
234
235
 
235
236
  /**
236
237
  * 使用css @keyframes动画,实现高亮行动画
237
- * 此方案作为兼容方式。v0.3.0 将使用Element.animate 接口实现动画。
238
+ * 此方案作为兼容方式。v0.3.4 将使用Element.animate 接口实现动画。
238
239
  */
239
240
  function highlightRowsInCssKeyframe(rowKeyValues: UniqKey[], className: string, duration: number) {
240
241
  /**是否需要重绘 */
@@ -267,7 +268,7 @@ export function useHighlight({ props, stkTableId, tableContainerRef }: Params) {
267
268
 
268
269
  /**
269
270
  * 使用css @keyframes动画,实现高亮单元格动画
270
- * 此方案作为兼容方式。v0.3.0 将使用Element.animate 接口实现动画。
271
+ * 此方案作为兼容方式。v0.3.4 将使用Element.animate 接口实现动画。
271
272
  */
272
273
  function highlightCellsInCssKeyFrame(cellEl: HTMLElement, rowKeyValue: UniqKey, className: string, duration: number) {
273
274
  if (cellEl.classList.contains(className)) {
@@ -143,16 +143,14 @@ export function useVirtualScroll<DT extends Record<string, any>>({
143
143
  * @param {number} [height] 虚拟滚动的高度
144
144
  */
145
145
  function initVirtualScrollY(height?: number) {
146
+ if (height !== void 0 && typeof height !== 'number') {
147
+ console.warn('initVirtualScrollY: height must be a number');
148
+ height = 0;
149
+ }
146
150
  if (!virtual_on.value) return;
147
151
  const { offsetHeight, scrollTop } = tableContainerRef.value || {};
148
152
  const { rowHeight } = virtualScroll.value;
149
- let containerHeight: number;
150
- // FIXME: 可能多次获取offsetHeight 会导致浏览器频繁重排
151
- if (typeof height === 'number') {
152
- containerHeight = height;
153
- } else {
154
- containerHeight = offsetHeight || DEFAULT_TABLE_HEIGHT;
155
- }
153
+ const containerHeight = height || offsetHeight || DEFAULT_TABLE_HEIGHT;
156
154
  const { headless, headerRowHeight } = props;
157
155
  let pageSize = Math.ceil(containerHeight / rowHeight);
158
156
  if (!headless) {
@@ -191,25 +189,19 @@ export function useVirtualScroll<DT extends Record<string, any>>({
191
189
  if (!virtual_on.value) return;
192
190
 
193
191
  let startIndex = Math.floor(sTop / rowHeight);
194
- if (props.stripe) {
195
- startIndex -= 1; //预渲染1行
196
- }
197
192
  if (startIndex < 0) {
198
193
  startIndex = 0;
199
194
  }
200
195
  if (props.stripe && startIndex !== 0) {
201
196
  const scrollRows = Math.abs(oldStartIndex - startIndex);
202
197
  // 斑马纹情况下,每滚动偶数行才加载。防止斑马纹错位。
203
- if (scrollRows < 2) {
204
- return;
205
- } else if (scrollRows % 2) {
198
+ if (scrollRows % 2) {
206
199
  startIndex -= 1; // 奇数-1变成偶数
207
200
  }
208
201
  }
209
202
  let endIndex = startIndex + pageSize;
210
203
  if (props.stripe) {
211
- // 由于stripe上方预渲染-1行,这里也要预渲染1+1行
212
- endIndex += 1;
204
+ endIndex += 1; // 斑马纹下多渲染一些
213
205
  }
214
206
  const offsetTop = startIndex * rowHeight; // startIndex之前的高度
215
207
  endIndex = Math.min(endIndex, dataSourceCopy.value.length); // 溢出index修正
@@ -241,17 +233,22 @@ export function useVirtualScroll<DT extends Record<string, any>>({
241
233
  function updateVirtualScrollX(sLeft = 0) {
242
234
  if (!props.virtualX) return;
243
235
  const headerLength = tableHeaderLast.value?.length;
244
- const { scrollLeft } = virtualScrollX.value;
245
236
  if (!headerLength) return;
237
+
238
+ const { scrollLeft } = virtualScrollX.value;
246
239
  let startIndex = 0;
247
240
  let offsetLeft = 0;
248
-
241
+ /** 列宽累加 */
249
242
  let colWidthSum = 0;
243
+ /** 固定左侧列宽 */
250
244
  let leftColWidthSum = 0;
245
+ /** 横向滚动时,第一列的剩余宽度 */
246
+ let leftFirstColRestWidth = 0;
247
+
251
248
  for (let colIndex = 0; colIndex < headerLength; colIndex++) {
252
- startIndex++;
253
249
  const col = tableHeaderLast.value[colIndex];
254
250
  const colWidth = getCalculatedColWidth(col);
251
+ startIndex++;
255
252
  // fixed left 不进入计算列宽
256
253
  if (col.fixed === 'left') {
257
254
  leftColWidthSum += colWidth;
@@ -262,11 +259,12 @@ export function useVirtualScroll<DT extends Record<string, any>>({
262
259
  if (colWidthSum >= sLeft) {
263
260
  offsetLeft = colWidthSum - colWidth;
264
261
  startIndex--;
262
+ leftFirstColRestWidth = colWidthSum - sLeft;
265
263
  break;
266
264
  }
267
265
  }
268
266
  // -----
269
- colWidthSum = 0;
267
+ colWidthSum = leftFirstColRestWidth;
270
268
  const containerWidth = virtualScrollX.value.containerWidth - leftColWidthSum;
271
269
  let endIndex = headerLength;
272
270
  for (let colIndex = startIndex + 1; colIndex < headerLength; colIndex++) {