feat(components): [virtual-table] Table (#7083)

* feat(components): [virtual-table] Table

- Add composable for column management.

* Update table props
This commit is contained in:
JeremyWuuuuu 2022-04-10 17:50:18 +08:00 committed by GitHub
parent 5849909577
commit 9a05d5cdc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 182 additions and 35 deletions

View File

@ -1,4 +1,4 @@
import { definePropType } from '@element-plus/utils' import { definePropType, mutable } from '@element-plus/utils'
import type { CSSProperties } from 'vue' import type { CSSProperties } from 'vue'
import type { Column, KeyType } from './types' import type { Column, KeyType } from './types'
@ -31,6 +31,11 @@ export const dataType = {
export const expandColumnKey = String export const expandColumnKey = String
export const expandKeys = {
type: definePropType<KeyType[]>(Array),
default: () => mutable([]),
} as const
export const requiredNumber = { export const requiredNumber = {
type: Number, type: Number,
required: true, required: true,
@ -38,7 +43,7 @@ export const requiredNumber = {
export const rowKey = { export const rowKey = {
type: definePropType<KeyType>([String, Number, Symbol]), type: definePropType<KeyType>([String, Number, Symbol]),
required: true, default: 'id',
} as const } as const
/** /**

View File

@ -20,11 +20,13 @@ export const tableV2HeaderProps = buildProps({
}, },
headerHeight: { headerHeight: {
type: definePropType<number | number[]>([Number, Array]), type: definePropType<number | number[]>([Number, Array]),
required: true, default: 50,
}, },
rowWidth: requiredNumberType, rowWidth: requiredNumberType,
rowHeight: requiredNumberType, rowHeight: {
type: Number,
default: 50,
},
height: requiredNumberType, height: requiredNumberType,
width: requiredNumberType, width: requiredNumberType,
} as const) } as const)

View File

@ -1,4 +1,16 @@
import { buildProps, definePropType } from '@element-plus/utils' import { buildProps, definePropType } from '@element-plus/utils'
import {
classType,
columns,
dataType,
expandKeys,
fixedDataType,
requiredNumber,
rowKey,
} from './common'
import { tableV2RowProps } from './row'
import { tableV2HeaderProps } from './header'
import { tableV2GridProps } from './grid'
import type { ExtractPropTypes, StyleValue } from 'vue' import type { ExtractPropTypes, StyleValue } from 'vue'
import type { import type {
@ -53,13 +65,17 @@ export type RowClassNameGetter<T> = (
export type ColumnSortHandler<T> = (params: ColumnSortParams<T>) => void export type ColumnSortHandler<T> = (params: ColumnSortParams<T>) => void
export const tableV2Props = buildProps({ export const tableV2Props = buildProps({
cache: tableV2GridProps.cache,
estimatedRowHeight: tableV2RowProps.estimatedRowHeight,
rowKey,
/** /**
* extra props deriver * extra props deriver
*/ */
cellProps: { cellProps: {
type: definePropType<any | ExtraCellPropGetter<any>>([Object, Function]), type: definePropType<any | ExtraCellPropGetter<any>>([Object, Function]),
}, },
headerClassName: { // Header attributes
headerClass: {
type: definePropType<string | HeaderClassNameGetter<any>>([ type: definePropType<string | HeaderClassNameGetter<any>>([
String, String,
Function, Function,
@ -77,55 +93,54 @@ export const tableV2Props = buildProps({
Function, Function,
]), ]),
}, },
rowClassName: { headerHeight: tableV2HeaderProps.headerHeight,
/**
* Footer attributes
*/
footerHeight: {
type: Number,
default: 0,
},
/**
* Row attributes
*/
rowClass: {
type: definePropType<string | RowClassNameGetter<any>>([String, Function]), type: definePropType<string | RowClassNameGetter<any>>([String, Function]),
}, },
rowProps: { rowProps: {
type: definePropType<any | ExtractRowPropGetter<any>>([Object, Function]), type: definePropType<any | ExtractRowPropGetter<any>>([Object, Function]),
}, },
rowHeight: Number,
/** /**
* Data models * Data models
*/ */
columns: { columns,
type: definePropType<Column<any>[]>(Array), data: dataType,
required: true, fixedData: fixedDataType,
},
fixedData: {
type: definePropType<any[]>(Array),
},
data: {
type: definePropType<any[]>(Array),
},
/** /**
* Expanded keys * Expanded keys
*/ */
expandedRowKeys: { expandColumnKey: tableV2RowProps.expandColumnKey,
type: definePropType<KeyType[]>(Array), expandedRowKeys: expandKeys,
}, defaultExpandedRowKeys: expandKeys,
defaultExpandedRowKeys: {
type: definePropType<KeyType[]>(Array),
},
/** /**
* Attributes * Attributes
*/ */
classNames: { class: classType,
type: definePropType<string | string[]>([String, Array]),
},
disabled: Boolean, disabled: Boolean,
footerHeight: { fixed: Boolean,
type: definePropType<number | number[]>([Number, Array]),
},
headerHeight: {
type: definePropType<number | number[]>([Number, Array]),
},
style: { style: {
type: definePropType<StyleValue>([String, Array, Object]), type: definePropType<StyleValue>([String, Array, Object]),
}, },
width: requiredNumber,
height: Number,
maxHeight: Number,
sortBy: { sortBy: {
type: definePropType<{ key: KeyType; order: SortOrder }>(Object), type: definePropType<{ key: KeyType; order: SortOrder }>(Object),
default: () => ({} as { key: KeyType; order: SortOrder }),
}, },
/** /**
@ -134,6 +149,10 @@ export const tableV2Props = buildProps({
onColumnSort: { onColumnSort: {
type: definePropType<ColumnSortParams<any>>(Function), type: definePropType<ColumnSortParams<any>>(Function),
}, },
onExpandedRowsChange: Function,
onRowExpand: Function,
onScroll: tableV2GridProps.onScroll,
rowEventHandlers: tableV2RowProps.rowEventHandlers,
} as const) } as const)
export type TableV2Props = ExtractPropTypes<typeof tableV2Props> export type TableV2Props = ExtractPropTypes<typeof tableV2Props>

View File

@ -1,4 +1,4 @@
import type { RendererElement, RendererNode, StyleValue, VNode } from 'vue' import type { CSSProperties, RendererElement, RendererNode, VNode } from 'vue'
import type { sortOrders } from './constants' import type { sortOrders } from './constants'
@ -69,7 +69,7 @@ export type Column<T = any> = {
maxWidth?: number maxWidth?: number
minWidth?: number minWidth?: number
resizable?: boolean resizable?: boolean
style?: StyleValue style?: CSSProperties
sortable?: boolean sortable?: boolean
width: number width: number
/** /**
@ -83,6 +83,8 @@ export type Column<T = any> = {
[key: string]: any [key: string]: any
} }
export type Columns<T> = Column<T>[]
export type CustomizedCellsType = VNode< export type CustomizedCellsType = VNode<
RendererNode, RendererNode,
RendererElement, RendererElement,

View File

@ -0,0 +1,119 @@
import { computed, unref } from 'vue'
import type { CSSProperties, Ref } from 'vue'
import type { Column, Columns } from './types'
const getColumnStyle = (
column: Column<any>,
fixedColumn: boolean
): CSSProperties => {
const style = {
...(column.style ?? {}),
width: column.width,
}
if (!fixedColumn) {
if (column.maxWidth) style.maxWidth = column.maxWidth
if (column.minWidth) style.maxWidth = column.minWidth
}
return style
}
function useColumns(columns: Ref<Columns<any>>, fixed: Ref<boolean>) {
let mappedColumnsCopy: Columns<any> = []
const mappedColumns = computed(() => {
const _columns = unref(columns)
const ret = _columns.map((column) => {
if (!column.resizable) return column
let { width } = column
if (column.resizable) {
const idx = _columns.findIndex(
(predicated) => column.key === predicated.key
)
if (idx >= 0 && _columns[idx].width === column.width) {
width = mappedColumnsCopy[idx].width
}
}
return {
...column,
width,
}
})
mappedColumnsCopy = ret
return ret
})
const visibleColumns = computed(() => {
return unref(mappedColumns).filter((column) => !column.hidden)
})
const fixedColumnsOnLeft = computed(() =>
unref(visibleColumns).filter(
(column) => column.fixed === 'left' || column.fixed === true
)
)
const fixedColumnOnRight = computed(() =>
unref(visibleColumns).filter((column) => column.fixed === 'right')
)
const normalColumns = computed(() =>
unref(visibleColumns).filter((column) => !column.fixed)
)
const mainColumns = computed(() => {
const ret: Columns<any> = []
unref(fixedColumnsOnLeft).forEach((column) => {
ret.push({
...column,
isPlaceholder: true,
})
})
unref(normalColumns).forEach((column) => {
ret.push(column)
})
unref(fixedColumnOnRight).forEach((column) => {
ret.push({
...column,
isPlaceholder: true,
})
})
return ret
})
const columnsStyle = computed(() => {
const columns = unref(mappedColumns)
return columns.reduce<Record<Column<any>['key'], CSSProperties>>(
(style, column) => {
style[column.key] = getColumnStyle(column, unref(fixed))
return style
},
{}
)
})
return {
columns: mappedColumns,
columnsStyle,
fixedColumnsOnLeft,
fixedColumnOnRight,
mainColumns,
normalColumns,
visibleColumns,
}
}
function useTable() {
// to be filled
}
export { useColumns, useTable }