mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat(components): [virtual-table] renderer (#7151)
- Add renderer for main table
This commit is contained in:
36
packages/components/table-v2/src/expand-icon.tsx
Normal file
36
packages/components/table-v2/src/expand-icon.tsx
Normal 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>
|
||||
@@ -55,7 +55,7 @@ export const tableV2GridProps = buildProps({
|
||||
/**
|
||||
* Event handlers
|
||||
*/
|
||||
onRowRendered: {
|
||||
onRowsRendered: {
|
||||
type: definePropType<(params: onRowRenderedParams) => void>(Function),
|
||||
},
|
||||
onScroll: {
|
||||
|
||||
@@ -59,7 +59,7 @@ const useTableGrid = (props: TableV2GridProps) => {
|
||||
rowVisibleStart,
|
||||
rowVisibleEnd,
|
||||
}: GridItemRenderedEvtParams) {
|
||||
props.onRowRendered?.({
|
||||
props.onRowsRendered?.({
|
||||
rowCacheStart,
|
||||
rowCacheEnd,
|
||||
rowVisibleStart,
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ export const tableV2Props = buildProps({
|
||||
type: definePropType<StyleValue>([String, Array, Object]),
|
||||
},
|
||||
width: requiredNumber,
|
||||
height: Number,
|
||||
height: requiredNumber,
|
||||
maxHeight: Number,
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user