feat(components): [virtual-table] renderer (#7151)

- Add renderer for main table
This commit is contained in:
JeremyWuuuuu
2022-04-13 22:21:47 +08:00
committed by GitHub
parent 0ecc6bc91e
commit d8a138ea38
7 changed files with 129 additions and 19 deletions

View File

@@ -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 (
<ElIcon {...expandIconProps}>
<CaretRight style={style} />
</ElIcon>
)
}
)
export default ExpandIcon
export type ExpandIconInstance = InstanceType<typeof ExpandIcon>

View File

@@ -55,7 +55,7 @@ export const tableV2GridProps = buildProps({
/**
* Event handlers
*/
onRowRendered: {
onRowsRendered: {
type: definePropType<(params: onRowRenderedParams) => void>(Function),
},
onScroll: {

View File

@@ -59,7 +59,7 @@ const useTableGrid = (props: TableV2GridProps) => {
rowVisibleStart,
rowVisibleEnd,
}: GridItemRenderedEvtParams) {
props.onRowRendered?.({
props.onRowsRendered?.({
rowCacheStart,
rowCacheEnd,
rowVisibleStart,

View File

@@ -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 (
<Table ref={mainTableRef} class={ns.e('main')} columns={unref(columns)}>
<Table
ref={mainTableRef}
cache={cache}
class={ns.e('main')}
columns={unref(mainColumns)}
data={data}
estimatedRowHeight={estimatedRowHeight}
bodyWidth={unref(bodyWidth)}
headerHeight={headerHeight}
headerWidth={unref(headerWidth)}
rowHeight={rowHeight}
height={unref(mainTableHeight)}
width={width}
onRowsRendered={onRowsRendered}
onScroll={onScroll}
>
{renderTableRow}
</Table>
)
@@ -130,6 +173,7 @@ const TableV2 = defineComponent({
columns,
column,
columnIndex,
expandIconProps,
isScrolling,
rowData,
rowIndex,
@@ -141,7 +185,7 @@ const TableV2 = defineComponent({
<div class={ns.em('row-cell', 'placeholder')} style={cellStyle} />
)
}
const { dataKey, dataGetter } = props
const { dataKey, dataGetter, rowKey } = props
const CellComponent = slots.cell || ((props) => <TableCell {...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 = <div></div>
// }
// {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 = (
<ExpandIcon
{...expandIconProps}
expanded={expanded}
expandable={expandable}
/>
)
}
return (
<div
@@ -188,6 +241,7 @@ const TableV2 = defineComponent({
style={cellStyle}
>
{Cell}
{Icon}
</div>
)
}

View File

@@ -144,7 +144,7 @@ export const tableV2Props = buildProps({
type: definePropType<StyleValue>([String, Array, Object]),
},
width: requiredNumber,
height: Number,
height: requiredNumber,
maxHeight: Number,
/**

View File

@@ -106,6 +106,13 @@ function useColumns(columns: Ref<AnyColumn>, fixed: Ref<boolean>) {
)
})
const columnsTotalWidth = computed(() => {
return unref(visibleColumns).reduce(
(width, column) => width + column.width,
0
)
})
watch(
columns,
(val) => {
@@ -132,6 +139,7 @@ function useColumns(columns: Ref<AnyColumn>, fixed: Ref<boolean>) {
return {
columns: _columns,
columnsStyles,
columnsTotalWidth,
fixedColumnsOnLeft,
fixedColumnOnRight,
hasFixedColumns,

View File

@@ -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<Heights>({})
const rightTableHeights = shallowRef<Heights>({})
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,