在ant上的table常见用法是一行的元素可编辑,如下:
但是现在有一个需求是全部单元格均可编辑,如何实现呢?
- 表格组件
<a-table
v-if="query.personnel_type === '0'"
size="middle"
row-key="id"
:scroll="{ x: 'max-content' }"
:columns="columns"
:data-source="data"
:loading="loading"
:pagination="false"
/>
- 表头数据
{
title: '月份',
width: 170,
dataIndex: 'created_at',
},
{
title: '基础员工(个)',
width: 120,
dataIndex: 'basic',
},
{
title: '高技能员工(个)',
width: 120,
dataIndex: 'senior',
},
{
title: '专业专家(个)',
width: 120,
dataIndex: 'expert',
},
{
title: '实习生(个)',
width: 120,
dataIndex: 'trainee',
},
- 效果
- 使用
<Input>
插槽可以Table组件内部渲染样式
在Table的Api第一行就显示的是具名插槽,使用这个插槽可以对表格内部数据个人化操作。
text, record, index, column
分别表示单元格的文本数据,一行的数据,索引和列的表头元素。一般情况下通过v-if
判断表头元素对该列做个性化。
- 具名插槽编辑
<a-table
v-if="query.personnel_type === '0'"
size="middle"
row-key="id"
:scroll="{ x: 'max-content' }"
:columns="columns"
:data-source="data"
:loading="loading"
:pagination="false"
>
<template
#bodyCell="{ record, column }"
>
<template
v-if="column.dataIndex === 'senior'"
>
<a-input
:placeholder="record[column.dataIndex]"
@change="(e) => handleChange(e.target.value, record, column)"
/>
</template>
</template>
</a-table>
关键代码
<template
#bodyCell="{ record, column }"
>
<template
v-if="column.dataIndex === 'senior'"
>
<a-input
:placeholder="record[column.dataIndex]"
@change="(e) => handleChange(e.target.value, record, column)"
/>
</template>
</template>
v-if="column.dataIndex === 'senior'"
判断表头是senior元素将其变成一个input输入框,效果如下:
- 实现全单元格编辑
对所需要全局编辑的表头做判断即可,如下:
<template
#bodyCell="{ record, column }"
>
<template
v-if="['basic', 'senior', 'expert', 'trainee'].includes(column.dataIndex)"
>
<a-input
:placeholder="record[column.dataIndex]"
@change="(e) => handleChange(e.target.value, record, column)"
/>
</template>
</template>
改造后就得到了除时间外全部单元格都可编辑的一个Table,但是在默认情况下并不比想要其展现可编辑状态,而是在点击某个按钮后显示可编辑状态。
- 编辑状态改变
基于该方式我们可以在输入框添加一个v-if
判断
<a-input
v-if="isShowGlobalEdit"
:placeholder="record[column.dataIndex]"
@change="(e) => handleChange(e.target.value, record, column)"
/>
在默认情况下就是忽略了input
插槽。
设置按钮绑定响应事件
// 全单元格编辑
isShowAllEdit() {
this.isShowGlobalEdit = true
},
cloneAllEdit() {
this.isShowGlobalEdit = false
},
这里情况下肯会不成功,应为表格已经渲染了,这时候再去改变
if
的状态已经无效了。这里有两种实现方法,第一种就是vue的钩子函数,把isShowGlobalEdit
在beforeUpdate()
重新赋值一下使表格重新渲染就可以了。另一种如下:
import { cloneDeep } from 'lodash/lang'
// 全单元格编辑
isShowAllEdit() {
this.isShowGlobalEdit = cloneDeep(this.isShowGlobalEdit === true)
},
cloneAllEdit() {
this.isShowGlobalEdit = cloneDeep(this.isShowGlobalEdit === false)
},
使用这种深度监听也可以实现,这个可以自行去查资料哈。
- 数据监听
到这里全单元格的编辑已经做出来了,但是如何获取数据呢?
在输入数据时,当鼠标移开数据就消失了,这是由于在vue中数据使响应式的,这里的输入并未改变实际的状态。在Table中提供了change
API帮助获取变化,如下:
<template
#bodyCell="{ record, column }"
>
<template
v-if="['basic', 'senior', 'expert', 'trainee'].includes(column.dataIndex)"
>
<a-input
v-if="isShowGlobalEdit"
:placeholder="record[column.dataIndex]"
@change="(e) => handleTableChange(e)"
/>
</template>
</template>
handleTableChange(e) {
console.log(e)
},
可以看到每次输入都会触发事件,控制台打印一个对象,这个对象肯定式包含输入值的,找出它即可,如下:
再次改造函数如下:
<template
#bodyCell="{ record, column }"
>
<template
v-if="['basic', 'senior', 'expert', 'trainee'].includes(column.dataIndex)"
>
<a-input
v-if="isShowGlobalEdit"
:placeholder="record[column.dataIndex]"
@change="(e) => handleTableChange(e.target.value, record, column)"
/>
</template>
</template>
e.target.value, record, column
这三个参数都是需要的。record, column
用于判断是那行的数据修改了,不然全局修改不知道是修改了哪些数据。
到此修改的数据就可以被实时获取了,接下来是组装数据,全局修改需要知道修改是那行的数据。
- 组装数据
一行的数据也传递到函数,如下:
由这些数据可以知道是那一行和那一列的数据,就可以组装了。
handleTableChange(e, record, column) {
record[column.dataIndex] = e
this.dataDuplication.push(record)
},
这样组装发信每次输入都会触发,导出数组重复数据,这里需要判断,由于id
是唯一的,可以根据id判断。如下:
handleTableChange(e, record, column) {
// 过滤重复id
this.dataDuplication = this.dataDuplication.filter((item) => item.id !== record.id)
record[column.dataIndex] = e
this.dataDuplication.push(record)
},
最终获取的数据是更改后具有id的数据,这样的数据传递到后端可以直接更具id修改。到此全部单元格修改已经完成了。