列位置拖动功能需要安装插件draggable,并在页面中引入。
//npm方式安装
npm i -S vuedraggable
//或使用yarn安装
yarn add vuedraggable
其他的废话不说直接上代码:
HTML部分:
<template>
<div>
<a-button @click="toggleColumnsVisible">显示/隐藏列</a-button>
<a-table :columns="newColumns" :dataSource="dataSource"> </a-table>
</div>
</template>
JS部分:
<script>
import { getAction, postAction } from '@api/manage'
import draggable from 'vuedraggable'
export default {
name: 'showColumnsTable',
components: {
draggable,
},
data() {
return {
tableId: 'showColumnsTable',
dataSource: [
{
key: '1',
name: '胡彦斌',
age: 32,
address: '西湖区湖底公园1号',
},
{
key: '2',
name: '胡彦祖',
age: 42,
address: '西湖区湖底公园1号',
},
],
columns: [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
width: 100,
visible: true,
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
width: 100,
visible: true,
},
{
title: '住址',
dataIndex: 'address',
key: 'address',
width: 100,
visible: true,
},
{
title: '操作',
dataIndex: 'action',
key: 'action',
fixed: 'right',
width: 100,
visible: true,
},
],
newColumns: [],
}
},
created() {
this.getVisibleColumns()
},
methods: {
getVisibleColumns() {
getAction('后端查询接口', { tableId: this.tableId })
.then((res) => {
if (res.result === null) {
this.updateVisibleColumns()
return
}
if (res.code !== 200) {
this.updateVisibleColumns()
return
}
let newColumns = JSON.parse(res.result)
//给columns赋保存的值,不直接将回参直接覆盖columns,是因为columns中可能有新增的列,再就是columns中的 customRender: function 是无法保存到后端的
this.columns.forEach((column) => {
let newColumn = newColumns.find((item) => item.dataIndex === column.dataIndex)
if (newColumn) {
column.visible = newColumn.visible
column.width = newColumn.width
}
})
this.columns.sort((a, b) => {
const indexA = newColumns.findIndex((item) => item.title === a.title)
const indexB = newColumns.findIndex((item) => item.title === b.title)
return indexA - indexB
})
this.updateVisibleColumns()
})
.catch((err) => {
this.updateVisibleColumns()
})
},
toggleColumnsVisible() {
let cloneColumns = JSON.parse(JSON.stringify(this.columns))
// 弹出显示隐藏列的对话框
this.$confirm({
title: '显示/隐藏列',
content: () => (
<div>
<draggable v-model={this.columns}>
{this.columns.map((column) => (
// 通过fixed属性来判断是否是固定列,固定列不允许隐藏和调整位置
<div class={column.fixed === 'right' ? 'notDisplay' : ''}>
<div style="width:49%; float: left;display:flex;align-items: center;">
<svg
focusable="false"
className=""
data-icon="drag"
width="1em"
height="1em"
fill="currentColor"
aria-hidden="true"
viewBox="64 64 896 896"
style="margin-right:3px;cursor: pointer"
>
<path d="M909.3 506.3L781.7 405.6a7.23 7.23 0 00-11.7 5.7V476H548V254h64.8c6 0 9.4-7 5.7-11.7L517.7 114.7a7.14 7.14 0 00-11.3 0L405.6 242.3a7.23 7.23 0 005.7 11.7H476v222H254v-64.8c0-6-7-9.4-11.7-5.7L114.7 506.3a7.14 7.14 0 000 11.3l127.5 100.8c4.7 3.7 11.7.4 11.7-5.7V548h222v222h-64.8c-6 0-9.4 7-5.7 11.7l100.8 127.5c2.9 3.7 8.5 3.7 11.3 0l100.8-127.5c3.7-4.7.4-11.7-5.7-11.7H548V548h222v64.8c0 6 7 9.4 11.7 5.7l127.5-100.8a7.3 7.3 0 00.1-11.4z"></path>
</svg>
<a-checkbox v-model={column.visible}>{column.title}</a-checkbox>
</div>
<div style="width:49%;margin-left: 51%;">
<span style="margin-right:3px">列宽:</span>
<a-input-number
size="small"
style="width:60%"
step="10"
v-model={column.width}
></a-input-number>
</div>
</div>
))}
</draggable>
</div>
),
onOk: () => {
this.updateVisibleColumns()
this.saveVisibleColumns()
},
onCancel: () => {
this.columns.forEach((column) => {
let newColumn = cloneColumns.find((item) => item.dataIndex === column.dataIndex)
if (newColumn) {
column.visible = newColumn.visible
column.width = newColumn.width
}
})
this.columns.sort((a, b) => {
const indexA = cloneColumns.findIndex((item) => item.title === a.title)
const indexB = cloneColumns.findIndex((item) => item.title === b.title)
return indexA - indexB
})
},
})
},
updateVisibleColumns() {
// 更新显示的列配置
this.newColumns = this.columns.filter((column) => column.visible)
},
saveVisibleColumns() {
// 将显示隐藏列的数据存储到后端
let params = {
hiddenColumns: JSON.stringify(this.columns),
tableId: this.tableId,
}
postAction('后端保存接口', params).then((res) => {
if (res.success) {
this.$message.success('操作成功')
} else {
this.$message.error(res.message)
}
})
},
},
}
</script>
后端接口的逻辑为:一个tableId字段用于区分table,一个hiddenColumns字段为JSON格式化后的前端列数据,一个userId字段用于区分用户(从token里取),新增编辑使用同一接口,如果tableId不存在则为新增,否则为编辑。
CSS部分:
<style scoped>
.notDisplay {
display: none;
}
</style>