github项目地址 ps:可以的话给个start 嘿嘿嘿
注: 项目中Eitem属性只是为了方便查看,实际使用中由于dataIndex值不固定 建议使用string代替
两个简单合并的实现原理见此链接
form表单及表格的合并实现原理见此链接
1、简单合并--推荐同步数据使用
优点:不需要我们去处理column
缺点:是若数据是异步加载,column需要设置为ref,相比于下面的法二更加损耗性能
stopKey用于节省性能,如案例中,确定合并位置只需要到【运行内存】即可,后续的列不用合并,则可以将stopKey值设置为EItem.attr3(运行内存的dataIndex为EItem.attr3)
<template>
<PageLayout :navs="['合并表格', '简单合并']" title="简单合并">
<a-table bordered :columns="resultColumns" :dataSource="list"></a-table>
</PageLayout>
</template>
<script setup lang="ts">
import { columns, list } from './config'
import { EItem } from './config'
import { getMergeColumn } from '@/utils/tools/easy-table-merge'
const resultColumns = getMergeColumn(columns, list, { stopKey: EItem.attr3 })
</script>
<style scoped></style>
效果如下
2、简单合并--推荐异步数据使用
优点: columns只需要一次设置,不许要作为动态传入
缺点:需要手动设置customCell
这个在上面的基础上做了改进,可以选择哪些列需要合并单元格,在开始时以数组的方式传入(注意是要连续列的dataIndex)
<template>
<PageLayout :navs="['合并表格', '合并表格(静态列)']" title="合并表格(静态列)">
<a-table bordered :columns="staticColumns" :dataSource="list"></a-table>
</PageLayout>
</template>
<script setup lang="ts">
import { addSpansValueInList } from '@/utils/tools/static-table-merge'
import { list, staticColumns } from './config'
import { EItem } from './config'
addSpansValueInList([EItem.scheme, EItem.attr1, EItem.attr2, EItem.attr3], list)
</script>
export const staticColumns: TableColumnType[] = [
{
title: '套餐',
dataIndex: EItem.scheme,
width: 120,
customCell: setCustomCell('scheme'),
},
{
title: '内存',
dataIndex: EItem.attr1,
width: 120,
customCell: setCustomCell('attr1'),
},
{
title: '颜色',
dataIndex: EItem.attr2,
width: 120,
customCell: setCustomCell('attr2'),
},
{
title: '运行内存',
dataIndex: EItem.attr3,
width: 120,
},
{
title: '进价',
dataIndex: 'price',
width: 120,
},
{
title: '售价',
dataIndex: 'price2',
width: 120,
},
]
效果与法一相同
3、form合并表格
效果:
使用如下,具体的作用和方法都写在注释中,代码下方说一些特殊的配置
<template>
<PageLayout :navs="['合并表格', '用户操作']" title="用户操作">
<a-form :model="form">
<a-row :gutter="8">
<a-col v-bind="spans" v-for="item in formGroup" :key="item.key">
<a-form-item v-model:value="form[item.key]" :label="item.label">
<a-select
mode="multiple"
v-model:value="form[item.key]"
:options="selectOptions[item.key]"
></a-select>
</a-form-item>
</a-col>
</a-row>
</a-form>
<a-table
:pagination="false"
bordered
:columns="resultColumns"
:dataSource="resultList"
>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'price'">
<a-input v-model:value="record.price"></a-input>
</template>
</template>
</a-table>
</PageLayout>
</template>
<script setup lang="ts">
import {
columnsWithForm as columns,
selectOptions,
formGroup,
spans,
} from './config'
import { userMergeByForm } from '@/composable/table/user-merge-by-form'
// 通过异步方式获取选项配置和默认选中值
const getSelectOptionApi = () => {
return Promise.resolve({
selectConfig: selectOptions,
// 下面的填入值可以没有
initForm: {
attr1: [4, 5],
attr3: [7, 9],
},
})
}
const { loadSelectOption, resultColumns, resultList, form } = userMergeByForm({
// 模拟从后端动态获取表单选项和表单默认值
getSelectOptionApi,
// 要渲染的列
fixColumns: columns,
// 固定值,可直接设置或通过函数返回值获取
fixColumnsConfig: {
price: (record: any) => {
if (record.attr1 === 4) {
return 16
}
return 18
},
price2: 20,
},
// 要渲染的表单数组
formGroup,
})
loadSelectOption()
console.log(resultList)
</script>
只说一些比较特殊的
`fixColumnsConfig`
{
...
fixColumnsConfig: {
price: (record: any) => {
if (record.attr1 === 4) {
return 16
}
return 18
},
price2: 20,
}
}
如上配置表示
对于price1 ,若行数据中attr1(即内存)选中值对于的value为4则默认设置值16,否则设置值为18,效果如下图
setSelectOptions
和setInitForm
我们期待后端在异步返回数据时格式如下
{
selectConfig: selectOptions,
initForm: {
attr1: [4, 5],
attr3: [7, 9],
},
}
但当他返回格式不是我们想要的 则可以利用上述两函数进行取值,从而获取我们想要的数据
如:
后端返回
const data = {
meta: {
selectConfig: {
scheme: [
{ label: '套餐一', value: 11 },
{ label: '套餐二', value: 12 },
],
attr1: [
{ label: '32G', value: 4 },
{ label: '64G', value: 5 },
{ label: '128G', value: 6 },
],
attr2: [
{ label: '红色', value: 1 },
{ label: '黄色', value: 2 },
{ label: '绿色', value: 3 },
],
attr3: [
{ label: '32G', value: 7 },
{ label: '64G', value: 8 },
{ label: '128G', value: 9 },
],
},
},
other: {
initForm: {
attr1: [4, 5],
attr3: [7, 9],
},
},
}
我们可以使用如下
其中res就是接口的返回值
const { loadSelectOption, resultColumns, resultList, form }=userMergeByForm({
....
setInitForm:(res)=>res.meta.other.initForm,
setSelectOptions: (res) => res.meta.selectOptions,
})