注意添加这个属性,会影响到有多少个层级的表头: :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-v2
fixed
: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 cells
const groupCells = []
let width = 0
let idx = 0
columns.forEach((column, columnIndex) => {
if (column.placeholderSign === TableV2Placeholder) {
groupCells.push(cells[columnIndex])
} else {
width += cells[columnIndex].props.column.width
idx++
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 = 0
idx = 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.LEFT
for (let i = 0; i < 3; i++) columns[i].sortable = true
const 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-v2
fixed
: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 cells
const groupCells = []
let width = 0
let idx = 0
columns.forEach((column, columnIndex) => {
if (column.placeholderSign === TableV2Placeholder) {
groupCells.push(cells[columnIndex])
} else {
width += cells[columnIndex].props.column.width
idx++
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 = 0
idx = 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.LEFT
for (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>