From d8a138ea385a770d712b709487ae63a9b78b1544 Mon Sep 17 00:00:00 2001
From: JeremyWuuuuu <15975785+JeremyWuuuuu@users.noreply.github.com>
Date: Wed, 13 Apr 2022 22:21:47 +0800
Subject: [PATCH] feat(components): [virtual-table] renderer (#7151)
- Add renderer for main table
---
.../components/table-v2/src/expand-icon.tsx | 36 +++++++++
packages/components/table-v2/src/grid.ts | 2 +-
.../components/table-v2/src/table-grid.tsx | 2 +-
packages/components/table-v2/src/table-v2.tsx | 78 ++++++++++++++++---
packages/components/table-v2/src/table.ts | 2 +-
.../components/table-v2/src/use-columns.ts | 8 ++
packages/components/table-v2/src/use-table.ts | 20 ++++-
7 files changed, 129 insertions(+), 19 deletions(-)
create mode 100644 packages/components/table-v2/src/expand-icon.tsx
diff --git a/packages/components/table-v2/src/expand-icon.tsx b/packages/components/table-v2/src/expand-icon.tsx
new file mode 100644
index 0000000000..ffb929a44e
--- /dev/null
+++ b/packages/components/table-v2/src/expand-icon.tsx
@@ -0,0 +1,36 @@
+import { defineComponent } from 'vue'
+import ElIcon from '@element-plus/components/icon'
+import { CaretRight } from '@element-plus/icons-vue'
+
+import type { TableV2RowCellRenderParam } from './table-row'
+
+const ExpandIcon = defineComponent(
+ (
+ props: TableV2RowCellRenderParam['expandIconProps'] & {
+ expanded: boolean
+ expandable: boolean
+ }
+ ) => {
+ const { expanded, expandable, onExpand } = props
+
+ const expandIconProps = {
+ onClick: expandable ? () => onExpand(!expanded) : undefined,
+ } as any
+
+ const style = expanded
+ ? {
+ transform: 'rotate(90deg)',
+ }
+ : undefined
+
+ return (
+
+
+
+ )
+ }
+)
+
+export default ExpandIcon
+
+export type ExpandIconInstance = InstanceType
diff --git a/packages/components/table-v2/src/grid.ts b/packages/components/table-v2/src/grid.ts
index af2e6330d7..1bd3eda3de 100644
--- a/packages/components/table-v2/src/grid.ts
+++ b/packages/components/table-v2/src/grid.ts
@@ -55,7 +55,7 @@ export const tableV2GridProps = buildProps({
/**
* Event handlers
*/
- onRowRendered: {
+ onRowsRendered: {
type: definePropType<(params: onRowRenderedParams) => void>(Function),
},
onScroll: {
diff --git a/packages/components/table-v2/src/table-grid.tsx b/packages/components/table-v2/src/table-grid.tsx
index d7b9ae206a..0e529d0998 100644
--- a/packages/components/table-v2/src/table-grid.tsx
+++ b/packages/components/table-v2/src/table-grid.tsx
@@ -59,7 +59,7 @@ const useTableGrid = (props: TableV2GridProps) => {
rowVisibleStart,
rowVisibleEnd,
}: GridItemRenderedEvtParams) {
- props.onRowRendered?.({
+ props.onRowsRendered?.({
rowCacheStart,
rowCacheEnd,
rowVisibleStart,
diff --git a/packages/components/table-v2/src/table-v2.tsx b/packages/components/table-v2/src/table-v2.tsx
index 6bdd2d9b13..132040be3d 100644
--- a/packages/components/table-v2/src/table-v2.tsx
+++ b/packages/components/table-v2/src/table-v2.tsx
@@ -1,7 +1,7 @@
-import { defineComponent, provide, unref } from 'vue'
+import { computed, defineComponent, provide, unref } from 'vue'
import { get } from 'lodash-unified'
import { useNamespace } from '@element-plus/hooks'
-import { isFunction } from '@element-plus/utils'
+import { isFunction, isObject } from '@element-plus/utils'
import { useTable } from './use-table'
import { tryCall } from './utils'
import { TableV2InjectionKey } from './tokens'
@@ -12,7 +12,9 @@ import { tableV2Props } from './table'
import Table from './table-grid'
import TableRow from './table-row'
import TableCell from './table-cell'
+import ExpandIcon from './expand-icon'
+import type { VNode } from 'vue'
import type { TableGridRowSlotParams } from './table-grid'
import type { TableV2RowCellRenderParam } from './table-row'
@@ -24,8 +26,12 @@ const TableV2 = defineComponent({
const ns = useNamespace('table-v2')
const {
- columns,
columnsStyles,
+ columnsTotalWidth,
+ // fixedColumnsOnLeft,
+ // fixedColumnOnRight,
+ mainColumns,
+ mainTableHeight,
depthMap,
expandedRowKeys,
hasFixedColumns,
@@ -33,14 +39,51 @@ const TableV2 = defineComponent({
mainTableRef,
isResetting,
isScrolling,
+ vScrollbarSize,
+ onScroll,
onRowHovered,
onRowExpanded,
+ onRowsRendered,
} = useTable(props)
+ const bodyWidth = computed(() => {
+ const { fixed, width } = props
+ const ret = width - unref(vScrollbarSize)
+ return fixed ? Math.max(Math.round(unref(columnsTotalWidth)), ret) : ret
+ })
+
+ const headerWidth = computed(
+ () => unref(bodyWidth) + (props.fixed ? unref(vScrollbarSize) : 0)
+ )
+
function renderMainTable() {
+ const {
+ cache,
+ data,
+ estimatedRowHeight,
+ headerHeight,
+ rowHeight,
+ width,
+ } = props
+
return (
-
+
)
@@ -130,6 +173,7 @@ const TableV2 = defineComponent({
columns,
column,
columnIndex,
+ expandIconProps,
isScrolling,
rowData,
rowIndex,
@@ -141,7 +185,7 @@ const TableV2 = defineComponent({
)
}
- const { dataKey, dataGetter } = props
+ const { dataKey, dataGetter, rowKey } = props
const CellComponent = slots.cell || ((props) => )
const cellData = isFunction(dataGetter)
@@ -167,13 +211,22 @@ const TableV2 = defineComponent({
column.align === Alignment.RIGHT && ns.em(scope, 'align-right'),
]
- // TODO: Add expand icon
- // expandIconProps,
- // let ExpandIcon
- // if (isObject(expandIconProps)) {
- // ExpandIcon =
- // }
- // {ExpandIcon}
+ const expanded =
+ rowIndex >= 0 && unref(expandedRowKeys).includes(rowData[rowKey])
+
+ const expandable = (rowData.children?.length ?? 0) > 0
+
+ let Icon: VNode | undefined
+
+ if (isObject(expandIconProps)) {
+ Icon = (
+
+ )
+ }
return (
{Cell}
+ {Icon}
)
}
diff --git a/packages/components/table-v2/src/table.ts b/packages/components/table-v2/src/table.ts
index 68ff8c805f..bc9bff2d5b 100644
--- a/packages/components/table-v2/src/table.ts
+++ b/packages/components/table-v2/src/table.ts
@@ -144,7 +144,7 @@ export const tableV2Props = buildProps({
type: definePropType([String, Array, Object]),
},
width: requiredNumber,
- height: Number,
+ height: requiredNumber,
maxHeight: Number,
/**
diff --git a/packages/components/table-v2/src/use-columns.ts b/packages/components/table-v2/src/use-columns.ts
index 6745d701d4..1c3ededbff 100644
--- a/packages/components/table-v2/src/use-columns.ts
+++ b/packages/components/table-v2/src/use-columns.ts
@@ -106,6 +106,13 @@ function useColumns(columns: Ref, fixed: Ref) {
)
})
+ const columnsTotalWidth = computed(() => {
+ return unref(visibleColumns).reduce(
+ (width, column) => width + column.width,
+ 0
+ )
+ })
+
watch(
columns,
(val) => {
@@ -132,6 +139,7 @@ function useColumns(columns: Ref, fixed: Ref) {
return {
columns: _columns,
columnsStyles,
+ columnsTotalWidth,
fixedColumnsOnLeft,
fixedColumnOnRight,
hasFixedColumns,
diff --git a/packages/components/table-v2/src/use-table.ts b/packages/components/table-v2/src/use-table.ts
index a8d12646ce..d699ce82a0 100644
--- a/packages/components/table-v2/src/use-table.ts
+++ b/packages/components/table-v2/src/use-table.ts
@@ -30,8 +30,12 @@ function useTable(props: TableV2Props) {
const {
columns,
columnsStyles,
- getColumn,
+ columnsTotalWidth,
+ fixedColumnsOnLeft,
+ fixedColumnOnRight,
hasFixedColumns,
+ mainColumns,
+ getColumn,
updateColumnWidth,
} = useColumns(toRef(props, 'columns'), toRef(props, 'fixed'))
// state
@@ -58,9 +62,9 @@ function useTable(props: TableV2Props) {
const mainTableHeights = shallowRef({})
const rightTableHeights = shallowRef({})
const hScrollbarSize = shallowRef(0)
- // const vScrollbarSize = shallowRef(0)
+ const vScrollbarSize = shallowRef(0)
- const tableHeight = computed(() => {
+ const mainTableHeight = computed(() => {
const { height = 0, maxHeight = 0, footerHeight } = props
if (maxHeight > 0) {
@@ -83,7 +87,7 @@ function useTable(props: TableV2Props) {
})
const windowHeight = computed(() => {
- return unref(tableHeight) - unref(headerHeight) - unref(fixedRowsHeight)
+ return unref(mainTableHeight) - unref(headerHeight) - unref(fixedRowsHeight)
})
function doScroll(params: ScrollPos) {
@@ -319,10 +323,18 @@ function useTable(props: TableV2Props) {
isScrolling,
hoveringRowKey,
hasFixedColumns,
+ hScrollbarSize,
+ vScrollbarSize,
// records
columnsStyles,
+ columnsTotalWidth,
expandedRowKeys,
depthMap,
+ fixedColumnsOnLeft,
+ fixedColumnOnRight,
+ mainColumns,
+ // metadata
+ mainTableHeight,
// methods
scrollTo,