@@ -56,12 +33,7 @@ export default defineComponent({
)
}
- return (
-
- {showMeasure.value && }
- {children}
-
- )
+ return {children}
}
},
})
diff --git a/packages/components/table/src/main/body/BodyCell.tsx b/packages/components/table/src/main/body/BodyCell.tsx
index 560fa3232..58fb977b5 100644
--- a/packages/components/table/src/main/body/BodyCell.tsx
+++ b/packages/components/table/src/main/body/BodyCell.tsx
@@ -20,7 +20,7 @@ import {
type TableColumnMergedExtra,
type TableColumnMergedSelectable,
} from '../../composables/useColumns'
-import { TABLE_TOKEN } from '../../token'
+import { TABLE_TOKEN, type TableBodyRowContext, tableBodyRowToken } from '../../token'
import {
type TableBodyCellProps,
type TableColumnIndexable,
@@ -51,8 +51,10 @@ export default defineComponent({
selectable,
mergedPagination,
} = inject(TABLE_TOKEN)!
+ const rowContext = inject(tableBodyRowToken)!
+ const rowProps = rowContext.props
const activeSortOrderBy = computed(() => activeOrderByMap[props.column.key])
- const dataValue = useDataValue(props)
+ const dataValue = useDataValue(rowContext, props)
const isFixStartLast = computed(() => fixedColumnKeys.value.lastStartKey === props.column.key)
const isFixEndFirst = computed(() => fixedColumnKeys.value.firstEndKey === props.column.key)
@@ -91,7 +93,7 @@ export default defineComponent({
}
const { starts, ends } = columnOffsets.value
const offsets = fixed === 'start' ? starts : ends
- const fixedOffset = convertCssPixel(offsets[props.colIndex])
+ const fixedOffset = convertCssPixel(offsets[props.column.key].offset)
return {
position: 'sticky',
left: fixed === 'start' ? fixedOffset : undefined,
@@ -107,19 +109,19 @@ export default defineComponent({
let title: string | undefined
if (type === 'selectable') {
- children = renderSelectableChildren(props, slots, selectable, config, mergedPagination)
+ children = renderSelectableChildren(rowContext, slots, selectable, config, mergedPagination)
} else if (type === 'indexable') {
- children = renderIndexableChildren(props, slots, column as TableColumnIndexable, mergedPagination)
+ children = renderIndexableChildren(rowContext, slots, column as TableColumnIndexable, mergedPagination)
} else {
const text = dataValue.value
- children = renderChildren(props, slots, text)
+ children = renderChildren(rowContext, props, slots, text)
title = getColTitle(mergedEllipsis.value, children, text)
// emptyCell 仅支持普通列
if (!type && (isNil(children) || children === '')) {
const emptyCellRender = slots.emptyCell || mergedEmptyCell.value
children = isFunction(emptyCellRender)
- ? emptyCellRender({ column, record: props.record, rowIndex: props.rowIndex })
+ ? emptyCellRender({ column, record: rowProps.record, rowIndex: rowProps.rowIndex })
: emptyCellRender
}
}
@@ -131,7 +133,7 @@ export default defineComponent({
const customAdditionalFn = tableProps.customAdditional?.bodyCell
const customAdditional = customAdditionalFn
- ? customAdditionalFn({ column, record: props.record, rowIndex: props.rowIndex })
+ ? customAdditionalFn({ column, record: rowProps.record, rowIndex: rowProps.rowIndex })
: undefined
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const Tag = (tableProps.customTag?.bodyCell ?? 'td') as any
@@ -139,7 +141,7 @@ export default defineComponent({
const contentNode =
type === 'expandable' ? (
- {renderExpandableChildren(props, slots, expandable, isTreeData, mergedPrefixCls.value)}
+ {renderExpandableChildren(rowContext, slots, expandable, isTreeData, mergedPrefixCls.value)}
{!isEmptyNode(children) && }
{children}
@@ -148,7 +150,14 @@ export default defineComponent({
)
return (
-
+
{contentNode}
)
@@ -156,9 +165,12 @@ export default defineComponent({
},
})
-function useDataValue(props: TableBodyCellProps) {
+function useDataValue(context: TableBodyRowContext, props: TableBodyCellProps) {
return computed(() => {
- const { column, record } = props
+ const {
+ props: { record },
+ } = context
+ const { column } = props
const dataKeys = convertArray(column.dataKey)
if (dataKeys.length <= 0) {
return undefined
@@ -177,22 +189,29 @@ function useDataValue(props: TableBodyCellProps) {
})
}
-function renderChildren(props: TableBodyCellProps, slots: Slots, value: string) {
- const { record, rowIndex, column } = props
+function renderChildren(context: TableBodyRowContext, props: TableBodyCellProps, slots: Slots, value: string) {
+ const {
+ props: { record, rowIndex },
+ } = context
+ const { column } = props
const { customCell } = column
const cellRender = isString(customCell) ? slots[customCell] : customCell
return cellRender ? cellRender({ value, record, rowIndex }) : value
}
function renderExpandableChildren(
- props: TableBodyCellProps,
+ context: TableBodyRowContext,
slots: Slots,
expandable: ComputedRef,
isTreeData: ComputedRef,
prefixCls: string,
) {
const { icon, customIcon, indent, showLine } = expandable.value!
- const { record, expanded, level = 0, hasPrevSibling, hasNextSibling, showLineIndentIndexList } = props
+ const {
+ props: { record, expanded, level = 0, hasPrevSibling, hasNextSibling, showLineIndentIndexList },
+ expandDisabled,
+ handleExpend,
+ } = context
const hasParent = level > 0
const mergedShowLine = isTreeData.value && showLine && indent
@@ -209,7 +228,7 @@ function renderExpandableChildren(
const triggerCls = {
[`${prefixCls}-expandable-trigger`]: true,
[`${prefixCls}-expandable-trigger-show-line`]: mergedShowLine,
- [`${prefixCls}-expandable-trigger-disabled`]: props.disabled,
+ [`${prefixCls}-expandable-trigger-disabled`]: expandDisabled.value,
}
const indents = []
@@ -234,7 +253,7 @@ function renderExpandableChildren(
@@ -248,48 +267,64 @@ function renderExpandableChildren(
}
function renderSelectableChildren(
- props: TableBodyCellProps,
+ rowContext: TableBodyRowContext,
slots: Slots,
selectable: ComputedRef,
config: TableConfig,
mergedPagination: ComputedRef,
) {
- const { record, rowIndex, selected: checked, indeterminate, disabled, isHover, handleSelect: onChange } = props
+ const {
+ props: { record, rowIndex },
+ isSelected,
+ isIndeterminate,
+ selectDisabled,
+ isHover,
+ handleSelect: onChange,
+ } = rowContext
const { showIndex, multiple, customCell } = selectable.value!
const onClick = (evt: Event) => {
// see https://github.com/IDuxFE/idux/issues/547
evt.stopPropagation()
// radio 支持反选
- if (!multiple && checked && !disabled && onChange) {
+ if (!multiple && isSelected.value && !selectDisabled.value && onChange) {
onChange()
}
}
- if (!checked && !isHover && showIndex) {
- return renderIndexableChildren(props, slots, config.columnIndexable as TableColumnIndexable, mergedPagination)
+ if (!isSelected.value && !isHover && showIndex) {
+ return renderIndexableChildren(rowContext, slots, config.columnIndexable as TableColumnIndexable, mergedPagination)
}
const customRender = isString(customCell) ? slots[customCell] : customCell
if (multiple) {
- const checkboxProps = { checked, disabled, indeterminate, onChange, onClick }
+ const checkboxProps = {
+ checked: isSelected.value,
+ disabled: selectDisabled.value,
+ indeterminate: isIndeterminate.value,
+ onChange,
+ onClick,
+ }
return customRender ? (
customRender({ ...checkboxProps, record, rowIndex })
) : (
)
} else {
- const radioProps = { checked, disabled, onChange, onClick }
+ const radioProps = { checked: isSelected.value, disabled: selectDisabled.value, onChange, onClick }
return customRender ? customRender({ ...radioProps, record, rowIndex }) :
}
}
function renderIndexableChildren(
- props: TableBodyCellProps,
+ context: TableBodyRowContext,
slots: Slots,
indexable: TableColumnIndexable,
mergedPagination: ComputedRef,
) {
- const { record, rowIndex, disabled } = props
+ const {
+ props: { record, rowIndex },
+ selectDisabled,
+ } = context
const { customCell } = indexable
const { pageIndex = 1, pageSize = 0 } = mergedPagination.value || {}
const customRender = isString(customCell) ? slots[customCell] : customCell
@@ -297,6 +332,6 @@ function renderIndexableChildren(
__DEV__ && Logger.warn('components/table', 'invalid customCell, please check the column is correct')
return undefined
}
- const style = disabled ? 'cursor: not-allowed' : 'cursor: pointer'
+ const style = selectDisabled.value ? 'cursor: not-allowed' : 'cursor: pointer'
return {customRender({ record, rowIndex, pageIndex, pageSize })}
}
diff --git a/packages/components/table/src/main/body/BodyRow.tsx b/packages/components/table/src/main/body/BodyRow.tsx
index 829e26ff1..430b7c4af 100644
--- a/packages/components/table/src/main/body/BodyRow.tsx
+++ b/packages/components/table/src/main/body/BodyRow.tsx
@@ -5,27 +5,21 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/
-import { type ComputedRef, Ref, type VNodeTypes, computed, defineComponent, inject, normalizeClass, ref } from 'vue'
+import { type ComputedRef, computed, defineComponent, inject, normalizeClass, provide, ref } from 'vue'
import { type VKey } from '@idux/cdk/utils'
-import BodyCell from './BodyCell'
-import {
- type TableColumnMerged,
- type TableColumnMergedExpandable,
- type TableColumnMergedSelectable,
-} from '../../composables/useColumns'
+import { type TableColumnMergedExpandable, type TableColumnMergedSelectable } from '../../composables/useColumns'
import { FlattedData } from '../../composables/useDataSource'
-import { TABLE_TOKEN } from '../../token'
+import { TABLE_TOKEN, tableBodyRowToken } from '../../token'
import { type TableBodyRowProps, tableBodyRowProps } from '../../types'
export default defineComponent({
props: tableBodyRowProps,
- setup(props) {
+ setup(props, { slots }) {
const {
props: tableProps,
mergedPrefixCls,
- flattedColumns,
expandable,
handleExpandChange,
checkExpandDisabled,
@@ -61,6 +55,17 @@ export default defineComponent({
})
})
+ provide(tableBodyRowToken, {
+ props,
+ expandDisabled,
+ handleExpend,
+ isSelected,
+ isIndeterminate,
+ selectDisabled,
+ handleSelect,
+ isHover,
+ })
+
return () => {
const customAdditionalFn = tableProps.customAdditional?.bodyRow
const customAdditional = customAdditionalFn
@@ -71,17 +76,7 @@ export default defineComponent({
return (
- {renderChildren(
- props,
- flattedColumns,
- expandDisabled,
- handleExpend,
- isSelected,
- isIndeterminate,
- selectDisabled,
- handleSelect,
- isHover,
- )}
+ {slots.default?.()}
)
}
@@ -156,54 +151,3 @@ function useEvents(
return { expandDisabled, handleExpend, selectDisabled, handleSelect, isHover, attrs }
}
-
-function renderChildren(
- props: TableBodyRowProps,
- flattedColumns: ComputedRef,
- expandDisabled: ComputedRef,
- handleExpend: () => void,
- isSelected: ComputedRef,
- isIndeterminate: ComputedRef,
- selectDisabled: ComputedRef,
- handleSelect: () => void,
- isHover: Ref,
-) {
- const children: VNodeTypes[] = []
- const { rowIndex, record, level, hasNextSibling, hasPrevSibling, showLineIndentIndexList } = props
- flattedColumns.value.forEach((column, colIndex) => {
- const { type, colSpan: getColSpan, rowSpan: getRowSpan, key } = column
- const colSpan = getColSpan?.(record, rowIndex)
- const rowSpan = getRowSpan?.(record, rowIndex)
- if (colSpan === 0 || rowSpan === 0) {
- return
- }
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const colProps: any = {
- colSpan: colSpan === 1 ? undefined : colSpan,
- rowSpan: rowSpan === 1 ? undefined : rowSpan,
- rowIndex,
- colIndex,
- record,
- column,
- level,
- hasNextSibling,
- hasPrevSibling,
- showLineIndentIndexList,
- key,
- }
- if (type === 'expandable') {
- colProps.expanded = props.expanded
- colProps.disabled = expandDisabled.value
- colProps.handleExpend = handleExpend
- } else if (type === 'selectable') {
- colProps.selected = isSelected.value
- colProps.indeterminate = isIndeterminate.value
- colProps.disabled = selectDisabled.value
- colProps.handleSelect = handleSelect
- colProps.isHover = isHover.value
- }
- children.push()
- })
-
- return children
-}
diff --git a/packages/components/table/src/main/body/MeasureCell.tsx b/packages/components/table/src/main/body/MeasureCell.tsx
index 34e81d135..ce4e273a2 100644
--- a/packages/components/table/src/main/body/MeasureCell.tsx
+++ b/packages/components/table/src/main/body/MeasureCell.tsx
@@ -17,8 +17,10 @@ export default defineComponent({
const cellRef = ref()
const handleResize = (evt: ResizeObserverEntry) => {
- const { offsetWidth } = evt.target as HTMLTableCellElement
- props.changeColumnWidth(props.cellKey, offsetWidth)
+ const {
+ contentRect: { width },
+ } = evt
+ props.changeColumnWidth(props.cellKey, width)
}
useResizeObserver(cellRef, handleResize)
diff --git a/packages/components/table/src/main/body/MeasureRow.tsx b/packages/components/table/src/main/body/MeasureRow.tsx
index 67ac882fd..e2f6c8938 100644
--- a/packages/components/table/src/main/body/MeasureRow.tsx
+++ b/packages/components/table/src/main/body/MeasureRow.tsx
@@ -5,17 +5,20 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/
-import { defineComponent, inject } from 'vue'
+import type { TableColumnMerged } from '../../composables/useColumns'
+
+import { type PropType, defineComponent, inject } from 'vue'
import MeasureCell from './MeasureCell'
import { TABLE_TOKEN, tableBodyToken } from '../../token'
export default defineComponent({
- setup() {
- const { mergedPrefixCls, flattedColumns } = inject(TABLE_TOKEN)!
+ props: { columns: Array as PropType },
+ setup(props) {
+ const { mergedPrefixCls } = inject(TABLE_TOKEN)!
const { changeColumnWidth } = inject(tableBodyToken)!
return () => {
- const children = flattedColumns.value.map(column => {
+ const children = props.columns?.map(column => {
const { key } = column
const cellProps = { key, cellKey: key, changeColumnWidth }
return
diff --git a/packages/components/table/src/main/body/RenderBodyCells.tsx b/packages/components/table/src/main/body/RenderBodyCells.tsx
new file mode 100644
index 000000000..fa4098357
--- /dev/null
+++ b/packages/components/table/src/main/body/RenderBodyCells.tsx
@@ -0,0 +1,51 @@
+/**
+ * @license
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
+ */
+
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
+
+import type { TableColumnMerged } from '../../composables/useColumns'
+import type { VNode } from 'vue'
+
+import BodyCell from './BodyCell'
+
+export function renderBodyCells(columns: TableColumnMerged[], record: any, rowIndex: number): VNode[] {
+ const children: VNode[] = []
+ columns.forEach((column, colIndex) => {
+ const cell = renderBodyCell(column, record, rowIndex, colIndex)
+
+ if (cell) {
+ children.push(cell)
+ }
+ })
+
+ return children
+}
+
+export function renderBodyCell(
+ column: TableColumnMerged,
+ record: any,
+ rowIndex: number,
+ colIndex: number,
+): VNode | undefined {
+ const { colSpan: getColSpan, rowSpan: getRowSpan } = column
+ const colSpan = getColSpan?.(record, rowIndex)
+ const rowSpan = getRowSpan?.(record, rowIndex)
+ if (colSpan === 0 || rowSpan === 0) {
+ return
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const colProps: any = {
+ colSpan: colSpan === 1 ? undefined : colSpan,
+ rowSpan: rowSpan === 1 ? undefined : rowSpan,
+ colIndex,
+ column,
+ }
+
+ return
+}
diff --git a/packages/components/table/src/main/body/RenderBodyRow.tsx b/packages/components/table/src/main/body/RenderBodyRow.tsx
index e0e158f90..42f51b42e 100644
--- a/packages/components/table/src/main/body/RenderBodyRow.tsx
+++ b/packages/components/table/src/main/body/RenderBodyRow.tsx
@@ -21,6 +21,7 @@ export function renderBodyRow(
slots: Slots,
expandable: TableColumnMergedExpandable | undefined,
prefixCls: string,
+ cols?: VNodeChild,
): VNodeChild {
const { children, expanded, level, hasPrevSibling, hasNextSibling, showLineIndentIndexList, record, rowKey } = item
const rowProps = {
@@ -36,7 +37,7 @@ export function renderBodyRow(
rowIndex,
rowKey,
}
- const rowNode =
+ const rowNode = {cols}
const expandedNode = expanded && renderExpandedContext(rowProps, slots, expandable, prefixCls)
return expandedNode ? [rowNode, expandedNode] : rowNode
diff --git a/packages/components/table/src/main/head/Head.tsx b/packages/components/table/src/main/head/Head.tsx
index 9c23bca32..609e04688 100644
--- a/packages/components/table/src/main/head/Head.tsx
+++ b/packages/components/table/src/main/head/Head.tsx
@@ -5,26 +5,37 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/
-import { defineComponent, inject } from 'vue'
+import { type VNodeChild, defineComponent, inject } from 'vue'
-import HeadRow from './HeadRow'
+import { renderHeaderCells } from './RenderHeaderCells'
+import { renderHeaderRow } from './RenderHeaderRow'
import { TABLE_TOKEN } from '../../token'
export default defineComponent({
- setup() {
+ setup(_, { slots }) {
const { props: tableProps, mergedRows, mergedPrefixCls } = inject(TABLE_TOKEN)!
return () => {
- const rows = mergedRows.value
+ let children: VNodeChild
+
+ const { rows } = mergedRows.value
const customAdditionalFn = tableProps.customAdditional?.head
const customAdditional = customAdditionalFn ? customAdditionalFn({ rows }) : undefined
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const Tag = (tableProps.customTag?.head ?? 'thead') as any
+
+ if (slots.default) {
+ children = slots.default()
+ } else {
+ children = rows.map((columns, rowIndex) => {
+ const cells = renderHeaderCells(columns)
+ return renderHeaderRow(columns, rowIndex, cells)
+ })
+ }
+
return (
- {rows.map((columns, rowIndex) => (
-
- ))}
+ {children}
)
}
diff --git a/packages/components/table/src/main/head/HeadCell.tsx b/packages/components/table/src/main/head/HeadCell.tsx
index 60c270778..c00d1fa33 100644
--- a/packages/components/table/src/main/head/HeadCell.tsx
+++ b/packages/components/table/src/main/head/HeadCell.tsx
@@ -51,6 +51,7 @@ export default defineComponent({
handleSort,
activeOrderByMap,
activeFilterByMap,
+ mergedRows,
handleFilter,
} = inject(TABLE_TOKEN)!
@@ -88,14 +89,16 @@ export default defineComponent({
})
const style = computed(() => {
- const { fixed, colStart, colEnd } = props.column as HeadColumn
+ const { key, fixed } = props.column as HeadColumn
+ const { offsetIndexMap } = mergedRows.value
if (!fixed) {
return
}
const { starts, ends } = columnOffsetsWithScrollBar.value
- const offsets = fixed === 'start' ? starts : ends
- const offsetIndex = fixed === 'start' ? colStart : colEnd
- const fixedOffset = convertCssPixel(offsets[offsetIndex])
+ const offsets = Object.values(fixed === 'start' ? starts : ends)
+ const offsetIndex = offsetIndexMap[key][fixed === 'start' ? 'colStart' : 'colEnd']
+
+ const fixedOffset = convertCssPixel(offsets.find(offset => offset.index === offsetIndex)?.offset)
return {
position: 'sticky',
left: fixed === 'start' ? fixedOffset : undefined,
diff --git a/packages/components/table/src/main/head/HeadRow.tsx b/packages/components/table/src/main/head/HeadRow.tsx
index 4517310e4..65ed4b648 100644
--- a/packages/components/table/src/main/head/HeadRow.tsx
+++ b/packages/components/table/src/main/head/HeadRow.tsx
@@ -7,13 +7,12 @@
import { defineComponent, inject } from 'vue'
-import HeadCell from './HeadCell'
import { TABLE_TOKEN } from '../../token'
import { tableHeadRowProps } from '../../types'
export default defineComponent({
props: tableHeadRowProps,
- setup(props) {
+ setup(props, { slots }) {
const { props: tableProps, mergedPrefixCls } = inject(TABLE_TOKEN)!
return () => {
@@ -24,11 +23,7 @@ export default defineComponent({
const Tag = (tableProps.customTag?.headRow ?? 'tr') as any
return (
- {columns
- .filter(column => column.titleColSpan !== 0)
- .map(column => (
-
- ))}
+ {slots.default?.()}
)
}
diff --git a/packages/components/table/src/main/head/RenderHeaderCells.tsx b/packages/components/table/src/main/head/RenderHeaderCells.tsx
new file mode 100644
index 000000000..b2dba6985
--- /dev/null
+++ b/packages/components/table/src/main/head/RenderHeaderCells.tsx
@@ -0,0 +1,23 @@
+/**
+ * @license
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
+ */
+
+import type { TableColumnMergedExtra } from '../../composables/useColumns'
+import type { VNode, VNodeChild } from 'vue'
+
+import HeadCell from './HeadCell'
+
+export function renderHeaderCells(columns: TableColumnMergedExtra[]): VNodeChild {
+ return columns.map(column => renderHeaderCell(column)).filter(Boolean)
+}
+
+export function renderHeaderCell(column: TableColumnMergedExtra): VNode | undefined {
+ if (column.titleColSpan === 0) {
+ return
+ }
+
+ return
+}
diff --git a/packages/components/table/src/main/head/RenderHeaderRow.tsx b/packages/components/table/src/main/head/RenderHeaderRow.tsx
new file mode 100644
index 000000000..6d6d1a086
--- /dev/null
+++ b/packages/components/table/src/main/head/RenderHeaderRow.tsx
@@ -0,0 +1,23 @@
+/**
+ * @license
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
+ */
+
+import type { TableColumnMergedExtra } from '../../composables/useColumns'
+import type { VNodeChild } from 'vue'
+
+import HeaderRow from './HeadRow'
+
+export function renderHeaderRow(
+ columns: TableColumnMergedExtra[],
+ index: number,
+ headerCells?: VNodeChild,
+): VNodeChild {
+ return (
+
+ {headerCells}
+
+ )
+}
diff --git a/packages/components/table/src/token.ts b/packages/components/table/src/token.ts
index 2dacd60bb..484db4edc 100644
--- a/packages/components/table/src/token.ts
+++ b/packages/components/table/src/token.ts
@@ -14,7 +14,8 @@ import type { ScrollContext } from './composables/useScroll'
import type { SelectableContext } from './composables/useSelectable'
import type { SortableContext } from './composables/useSortable'
import type { StickyContext } from './composables/useSticky'
-import type { TableEmptyCellOptions, TableProps } from './types'
+import type { TableBodyRowProps, TableEmptyCellOptions, TableProps } from './types'
+import type { VirtualScrollEnabled } from '@idux/cdk/scroll'
import type { VKey } from '@idux/cdk/utils'
import type { TableConfig } from '@idux/components/config'
import type { Locale } from '@idux/components/locales'
@@ -38,7 +39,9 @@ export interface TableContext
mergedAutoHeight: ComputedRef
mergedEmptyCell: ComputedRef VNodeChild) | undefined>
mergedInsetShadow: ComputedRef
+ mergedVirtual: ComputedRef
mergedVirtualItemHeight: ComputedRef
+ mergedVirtualColWidth: ComputedRef
tableLayout: ComputedRef<'auto' | 'fixed'>
}
@@ -50,4 +53,16 @@ export interface TableBodyContext {
changeColumnWidth: (key: VKey, width: number | false) => void
}
+export interface TableBodyRowContext {
+ props: TableBodyRowProps
+ expandDisabled: ComputedRef
+ handleExpend: () => void
+ isSelected: ComputedRef
+ isIndeterminate: ComputedRef
+ selectDisabled: ComputedRef
+ handleSelect: () => void
+ isHover: Ref
+}
+
export const tableBodyToken: InjectionKey = Symbol('tableBodyToken')
+export const tableBodyRowToken: InjectionKey = Symbol('tableBodyRowToken')
diff --git a/packages/components/table/src/types.ts b/packages/components/table/src/types.ts
index d256c6a39..ac6ae62ef 100644
--- a/packages/components/table/src/types.ts
+++ b/packages/components/table/src/types.ts
@@ -48,7 +48,11 @@ export const tableProps = {
scrollToTopOnChange: { type: Boolean, default: undefined },
tableLayout: { type: String as PropType<'auto' | 'fixed'>, default: undefined },
virtual: { type: Boolean, default: false },
+ virtualHorizontal: { type: Boolean, default: false },
virtualItemHeight: { type: Number, default: undefined },
+ virtualColWidth: { type: Number, default: undefined },
+ virtualBufferSize: { type: Number, default: undefined },
+ virtualBufferOffset: { type: Number, default: undefined },
// events
'onUpdate:expandedRowKeys': [Function, Array] as PropType void>>,
@@ -258,19 +262,8 @@ export type TableBodyRowProps = ExtractInnerPropTypes
export const tableBodyCellProps = {
column: { type: Object as PropType, required: true },
colIndex: { type: Number, required: true },
- level: { type: Number, default: undefined },
- record: { type: Object as PropType, required: true },
- rowIndex: { type: Number, required: true },
- disabled: { type: Boolean, default: undefined },
- expanded: { type: Boolean, default: undefined },
- hasPrevSibling: { type: Boolean, default: undefined },
- hasNextSibling: { type: Boolean, default: undefined },
- showLineIndentIndexList: { type: Array as PropType, default: () => [] },
- handleExpend: { type: Function as PropType<() => void>, default: undefined },
- isHover: { type: Boolean, default: undefined },
- selected: { type: Boolean, default: undefined },
- indeterminate: { type: Boolean, default: undefined },
- handleSelect: { type: Function as PropType<() => void>, default: undefined },
+ colSpan: Number,
+ rowSpan: Number,
} as const
export type TableBodyCellProps = ExtractInnerPropTypes
diff --git a/packages/components/table/src/utils/index.ts b/packages/components/table/src/utils/index.ts
index 4e673ffd4..60e798c4c 100644
--- a/packages/components/table/src/utils/index.ts
+++ b/packages/components/table/src/utils/index.ts
@@ -7,12 +7,15 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
+import type { TableColumnMerged, TableColumnScrollBar } from '../composables/useColumns'
+
import { Text, type VNodeChild } from 'vue'
import { isNumber, isObject, isString } from 'lodash-es'
import { Logger, type VKey, convertArray, flattenNode, uniqueId } from '@idux/cdk/utils'
+import { type FlattedData } from '../composables/useDataSource'
import { type TableColumn } from '../types'
export function getColTitle(
@@ -56,3 +59,55 @@ export function getColumnKey(column: TableColumn): VKey {
return uniqueId('__IDUX_table_column_key_')
}
+
+interface ModifiedData {
+ data: TableColumnMerged | TableColumnScrollBar
+ index: number
+ poolKey: string
+}
+
+export function modifyVirtualData(
+ renderedRow: FlattedData,
+ renderedCols: TableColumnMerged[],
+ flattedColumns: TableColumnMerged[],
+ flattedData: FlattedData[],
+ fixedStartColumns: (TableColumnMerged | TableColumnScrollBar)[],
+ fixedEndColumns: (TableColumnMerged | TableColumnScrollBar)[],
+ includeScrollBar = false,
+):
+ | {
+ start?: ModifiedData[]
+ end?: ModifiedData[]
+ }
+ | undefined {
+ const filterColumns = (columns: (TableColumnMerged | TableColumnScrollBar)[]) =>
+ columns.filter(column => column.type !== 'scroll-bar')
+
+ const startColumns = includeScrollBar ? fixedStartColumns : filterColumns(fixedStartColumns)
+ const endColumns = includeScrollBar ? fixedEndColumns : filterColumns(fixedEndColumns)
+
+ if (!startColumns.length && !endColumns.length) {
+ return
+ }
+
+ const rowIndex = flattedData.findIndex(data => data.rowKey === renderedRow.rowKey)
+
+ const getAppendedColumn = (column: TableColumnMerged | TableColumnScrollBar) => {
+ if (renderedCols.findIndex(col => col.key === column.key) > -1) {
+ return
+ }
+
+ const index = flattedColumns.findIndex(col => col.key === column.key)
+
+ return {
+ data: column,
+ index,
+ poolKey: `fix-${rowIndex}-${index}`,
+ }
+ }
+
+ return {
+ start: startColumns.map(getAppendedColumn).filter(Boolean) as ModifiedData[],
+ end: endColumns.map(getAppendedColumn).filter(Boolean) as ModifiedData[],
+ }
+}
diff --git a/packages/components/table/style/index.less b/packages/components/table/style/index.less
index 863fc5665..f5699d0cd 100644
--- a/packages/components/table/style/index.less
+++ b/packages/components/table/style/index.less
@@ -41,10 +41,6 @@
&::after {
right: 0;
}
-
- .cdk-virtual-scroll-holder {
- overflow-y: scroll;
- }
}
table {
@@ -190,6 +186,7 @@
flex-grow: 1;
}
+ &-body-virtual-scroll,
&-content {
flex-basis: 0;
height: 0;
@@ -200,15 +197,10 @@
flex-shrink: 0;
}
}
-
- .cdk-virtual-scroll {
- flex: 1 1 0;
- }
}
&-empty&-auto-height,
&-empty&-full-height {
- .cdk-virtual-scroll-filler,
.cdk-virtual-scroll-content,
table {
height: 100%;
diff --git a/packages/pro/table/demo/MasiveColumns.md b/packages/pro/table/demo/MasiveColumns.md
new file mode 100644
index 000000000..214ea44af
--- /dev/null
+++ b/packages/pro/table/demo/MasiveColumns.md
@@ -0,0 +1,12 @@
+---
+order: 11
+title:
+ zh: 大量数据列
+ en: Masive Columns
+---
+
+## zh
+
+可以通过开启横向虚拟滚动来支持大量数据列渲染的场景
+
+## en
diff --git a/packages/pro/table/demo/MasiveColumns.vue b/packages/pro/table/demo/MasiveColumns.vue
new file mode 100644
index 000000000..2a82683e9
--- /dev/null
+++ b/packages/pro/table/demo/MasiveColumns.vue
@@ -0,0 +1,132 @@
+
+
+
+ {{ value }}
+
+
+ Invite {{ record.name }}
+ Delete
+
+
+
+
+
diff --git a/packages/pro/table/demo/Resizable.vue b/packages/pro/table/demo/Resizable.vue
index bdc0b0e2c..42c6288ce 100644
--- a/packages/pro/table/demo/Resizable.vue
+++ b/packages/pro/table/demo/Resizable.vue
@@ -44,6 +44,7 @@ const columns: ProTableColumn[] = [
{
type: 'indexable',
changeVisible: false,
+ width: 60,
},
{
title: 'Name',