注意添加这个属性,会影响到有多少个层级的表头: :header-height=“[50, 40]”,即后面的columnIndex
如果有fix的列CustomizedHeader会被调用多次,如果有多个层级的表头,也会被调用多次, 实际被调用次数是(fix数+ 1 * 表头层级数量)
以下代码均删除了JSX
TS版本代码
<template><div style="width: 100%;height: calc(100vh - 84px)"><el-auto-resizer><template #default="{ height, width }"><el-table-v2fixed:columns="columns":data="data":sort-by="sortBy":header-height="[50, 40]":header-class="headerClass"@column-sort="onSort":width="width":height="height"><template #header="props"><customized-header v-bind="props"></customized-header></template></el-table-v2></template></el-auto-resizer></div>
</template><script lang="ts" setup>
import {h, ref} from 'vue'
import {TableV2FixedDir, TableV2Placeholder, TableV2SortOrder} from 'element-plus'
import type {HeaderClassNameGetter,TableV2CustomizedHeaderSlotParam,
} from 'element-plus'
import type {SortBy} from 'element-plus'
function generateColumns(length = 10, prefix = 'column-', props?: any) {return Array.from({length}).map((_, columnIndex) => ({...props,key: `${prefix}${columnIndex}`,dataKey: `${prefix}${columnIndex}`,title: `Column ${columnIndex}`,width: 150,}))
}function generateData(columns: ReturnType<typeof generateColumns>,length = 200,prefix = 'row-'
) {return Array.from({ length }).map((_, rowIndex) => {return columns.reduce((rowData, column, columnIndex) => {rowData[column.dataKey] = `Row ${rowIndex} - Col ${columnIndex}`return rowData},{id: `${prefix}${rowIndex}`,parentId: null,})})
}function CustomizedHeader({cells, columns, headerIndex}) {if (headerIndex === 1) return cellsconst groupCells = []let width = 0let idx = 0columns.forEach((column, columnIndex) => {if (column.placeholderSign === TableV2Placeholder) {groupCells.push(cells[columnIndex])} else {width += cells[columnIndex].props.column.widthidx++const nextColumn = columns[columnIndex + 1]if (columnIndex === columns.length - 1 ||nextColumn?.placeholderSign === TableV2Placeholder ||idx === (headerIndex === 0 ? 4 : 2)) {groupCells.push(h('div',{class: 'flex items-center justify-center custom-header-cell',role: 'columnheader',style: {...cells[columnIndex].props.style,width: `${width}px`,border: `2px solid #fff`}},`Group width ${width}`))width = 0idx = 0}}})return groupCells;
}const headerClass = ({headerIndex,}: Parameters<HeaderClassNameGetter<any>>[0]) => {if (headerIndex === 0) return 'el-primary-color'return ''
}const columns = generateColumns(70)
let data = generateData(columns, 20)columns[0].fixed = TableV2FixedDir.LEFTfor (let i = 0; i < 3; i++) columns[i].sortable = trueconst sortBy = ref<SortBy>({key: 'column-0',order: TableV2SortOrder.ASC,
})const onSort = (_sortBy: SortBy) => {data = data.reverse()sortBy.value = _sortBy
}
</script><style>
.el-el-table-v2__header-row .custom-header-cell {border-right: 1px solid var(--el-border-color);
}.el-el-table-v2__header-row .custom-header-cell:last-child {border-right: none;
}.el-primary-color {background-color: var(--el-color-primary);color: var(--el-color-white);font-size: 14px;font-weight: bold;
}.el-primary-color .custom-header-cell {padding: 0 4px;
}
</style>
JS版本
<template><div style="width: 100%;height: calc(100vh - 84px)"><el-auto-resizer><template #default="{ height, width }"><el-table-v2fixed:columns="columns":data="data":sort-by="sortBy":header-height="[50, 40]":header-class="headerClass"@column-sort="onSort":width="width":height="height"><template #header="props"><CustomizedHeader v-bind="props"></CustomizedHeader></template></el-table-v2></template></el-auto-resizer></div>
</template><script setup>
import { h, ref } from 'vue'
import {TableV2FixedDir,TableV2Placeholder,TableV2SortOrder
} from 'element-plus'
function generateColumns(length = 10, prefix = 'column-') {return Array.from({ length }).map((_, columnIndex) => ({key: `${prefix}${columnIndex}`,dataKey: `${prefix}${columnIndex}`,title: `Column ${columnIndex}`,width: 150}))
}function generateData(columns, length = 200, prefix = 'row-') {return Array.from({ length }).map((_, rowIndex) => {return columns.reduce((rowData, column, columnIndex) => {rowData[column.dataKey] = `Row ${rowIndex} - Col ${columnIndex}`return rowData},{id: `${prefix}${rowIndex}`,parentId: null})})
}function CustomizedHeader({ cells, columns, headerIndex }) {if (headerIndex === 1) return cellsconst groupCells = []let width = 0let idx = 0columns.forEach((column, columnIndex) => {if (column.placeholderSign === TableV2Placeholder) {groupCells.push(cells[columnIndex])} else {width += cells[columnIndex].props.column.widthidx++const nextColumn = columns[columnIndex + 1]if (columnIndex === columns.length - 1 ||nextColumn?.placeholderSign === TableV2Placeholder ||idx === (headerIndex === 0 ? 4 : 2)) {groupCells.push(h('div',{class: 'flex items-center justify-center custom-header-cell',role: 'columnheader',style: {...cells[columnIndex].props.style,width: `${width}px`,border: `2px solid #fff`}},`Group width ${width}`))width = 0idx = 0}}})return groupCells
}const headerClass = ({ headerIndex }) => {return headerIndex === 0 ? 'el-primary-color' : ''
}const columns = generateColumns(70)
let data = generateData(columns, 20)columns[0].fixed = TableV2FixedDir.LEFTfor (let i = 0; i < 3; i++) {columns[i].sortable = true
}const sortBy = ref({key: 'column-0',order: TableV2SortOrder.ASC
})const onSort = (_sortBy) => {data = [...data].reverse()sortBy.value = _sortBy
}</script><style>
.el-el-table-v2__header-row .custom-header-cell {border-right: 1px solid var(--el-border-color);
}.el-el-table-v2__header-row .custom-header-cell:last-child {border-right: none;
}.el-primary-color {background-color: var(--el-color-primary);color: var(--el-color-white);font-size: 14px;font-weight: bold;
}.el-primary-color .custom-header-cell {padding: 0 4px;
}
</style>