在ant上的table常见用法是一行的元素可编辑,如下:
但是现在有一个需求是全部单元格均可编辑,如何实现呢?
- 表格组件
<a-tablev-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-tablev-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 }"><templatev-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 }"><templatev-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 }"
><templatev-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-inputv-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 }"
><templatev-if="['basic', 'senior', 'expert', 'trainee'].includes(column.dataIndex)"><a-inputv-if="isShowGlobalEdit":placeholder="record[column.dataIndex]"@change="(e) => handleTableChange(e)"/></template>
</template>
handleTableChange(e) {console.log(e)},
可以看到每次输入都会触发事件,控制台打印一个对象,这个对象肯定式包含输入值的,找出它即可,如下:
再次改造函数如下:
<template#bodyCell="{ record, column }"
><templatev-if="['basic', 'senior', 'expert', 'trainee'].includes(column.dataIndex)"><a-inputv-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] = ethis.dataDuplication.push(record)
},
这样组装发信每次输入都会触发,导出数组重复数据,这里需要判断,由于id
是唯一的,可以根据id判断。如下:
handleTableChange(e, record, column) {// 过滤重复idthis.dataDuplication = this.dataDuplication.filter((item) => item.id !== record.id)record[column.dataIndex] = ethis.dataDuplication.push(record)
},
最终获取的数据是更改后具有id的数据,这样的数据传递到后端可以直接更具id修改。到此全部单元格修改已经完成了。