最近发现一个挺好用的拖拽排序插件awe-dnd ,刚好又在学习ant design,所以萌发了让table表格可自定义位置和自定义显隐的想法,用了俩个多小时把这个想法实现了。
1. 先去安装awe-dnd , awe-dnd npm链接 :https://www.npmjs.com/package/awe-dnd
$ npm install awe-dnd --save
2. 再mian.js中配置
//main.js
import VueDND from 'awe-dnd'
Vue.use(VueDND)
3. 在components 建一个drag文件夹 用来制作组件方便重复使用
3.1 文件夹中新建drag.vue
//drag.vue
<template>
<div>
<a-popover :title="popoverTitle" trigger="click">
<a slot="content">
<div class="color-list">
<div class="color-item" v-for="(color,index) in colors" v-dragging="{ item: color, list: colors, group: 'color' }"
:key="color.text">
<a>
<a-checkbox @change="onChange(index)" :checked="color.checked">{{color.text}}</a-checkbox>
</a>
</div>
</div>
</a>
<a-button type="primary">{{butTitle}}</a-button>
</a-popover>
</div>
</template>
<script>
export default {
props: ['butTitle','popover' ,'columnsData', 'colorsData'],
data() {
return {
butName:'',
popoverTitle:'',
columnsAll: [],
columnsAllcache: {},
colors: [],
colorsArry: [],
columns: []
}
},
methods: {
rf: function() {
this.colorsArry = this.colors
this.getDrag()
},
getDrag: function() {
//columnsAllcache 用来存放全部包裹头部信息 构建以头部信息key为索引对象的数据结构
var columnsAllcache = {}
for (var i = 0; i < this.columnsAll.length; i++) {
columnsAllcache[this.columnsAll[i].scopedSlots.customRender] = this.columnsAll[i]
}
this.columns = []
//循环排序数组 获取最新文字信息和显隐信息
for (var m = 0; m < this.colorsArry.length; m++) {
var columnsItem = this.colorsArry[m]
if (columnsItem.checked) { //判断排序数组中checked为选中的一项 将其放入columns 数组中 做为要展示的头部信息
this.columns.push(columnsAllcache[columnsItem.key])
}
}
this.$emit('onChange', this.columns) //触发回调方法
},
onChange: function(index) {
this.colorsArry[index].checked = !this.colorsArry[index].checked
this.getDrag()
},
},
mounted() {
this.$dragging.$on('dragged', ({
value
}) => {
this.colorsArry = value.list
this.getDrag()
})
this.$dragging.$on('dragend', () => {
})
this.colors = this.colorsData==undefined?[]:this.colorsData //接收要排序的数组
this.columnsAll = this.columnsData==undefined?[]:this.columnsData //接收表格全部的信息
this.butName = this.butTitle==undefined?'':this.butTitle //按钮名称
this.popoverTitle = this.popover==undefined?'':this.popover //气泡框标题
this.rf()
}
}
</script>
3.2再在文件夹下新建index.js 和drag.vue 保持一致
import Drag from './drag.vue'
export default Drag
4. 回到需要引入该组件的页面 我这里是table.vue
//table.vue
<template>
<div>
<!--Drag 可配置项 butTitle按钮文字(可为空) popover气泡框title(可为空)columnsData所有的完整的表格头部信息(不可为空)colorsData(用来排序的数组 可为空)-->
<Drag butTitle="点击排序" popover='表格排序' :columnsData='columnsAll' :colorsData='colors' @onChange='setColumns'></Drag>
<div style="margin-top: 200px;">
<a-table :columns="columns" :dataSource="data" bordered>
<template v-for="col in ['name', 'age', 'address']" :slot="col" slot-scope="text, record, index">
<div :key="col">
<a-input v-if="record.editable" style="margin: -5px 0" :value="text" @change="e => handleChange(e.target.value, record.key, col)" />
<template v-else>{{text}}</template>
</div>
</template>
<template slot="operation" slot-scope="text, record, index">
<div class='editable-row-operations'>
<span v-if="record.editable">
<a @click="() => save(record.key)">Save</a>
<a-popconfirm title='Sure to cancel?' @confirm="() => cancel(record.key)">
<a>Cancel</a>
</a-popconfirm>
</span>
<span v-else>
<a @click="() => edit(record.key)">Edit</a>
</span>
</div>
</template>
</a-table>
</div>
</div>
</template>
<script>
import Drag from '@/components/drag' //引入drag组件
const data = []
for (let i = 0; i < 100; i++) {
data.push({
key: i.toString(),
name: `Edrward ${i}`,
age: 32,
address: `London Park no. ${i}`,
})
}
export default {
components:{
Drag,
},
data() {
return {
data, //data 为表格数据
columnsAll: [{ //columnsAll为该表单中所有的头部数据
title: 'name',
dataIndex: 'name',
width: '25%',
scopedSlots: {
customRender: 'name'
},
}, {
title: 'age',
dataIndex: 'age',
width: '15%',
scopedSlots: {
customRender: 'age'
},
}, {
title: 'address',
dataIndex: 'address',
width: '40%',
scopedSlots: {
customRender: 'address'
},
}, {
title: 'operation',
dataIndex: 'operation',
scopedSlots: {
customRender: 'operation'
},
}],
columns:[], //表格最终要展示的头部信息
colors:[{ // colors数组的想法是基于从数据库中取要展示的头部信息
'text':'name',
'key':'name',
'checked':true
},
{
'text':'age',
'key':'age',
'checked':true
},
{
'text':'address',
'key':'address',
'checked':false
},
{
'text':'operation',
'key':'operation',
'checked':true
}
],
}
},
methods: {
setColumns:function (val) { //drag组件 改变时回调该方法 回调回来的val 是表格最终的头部信息
this.columns=val
},
//以下是ant table方法
handleChange(value, key, column) {
const newData = [...this.data]
const target = newData.filter(item => key === item.key)[0]
if (target) {
target[column] = value
this.data = newData
}
},
edit(key) {
const newData = [...this.data]
const target = newData.filter(item => key === item.key)[0]
if (target) {
target.editable = true
this.data = newData
}
},
save(key) {
const newData = [...this.data]
const target = newData.filter(item => key === item.key)[0]
if (target) {
delete target.editable
this.data = newData
this.cacheData = newData.map(item => ({ ...item
}))
}
},
cancel(key) {
const newData = [...this.data]
const target = newData.filter(item => key === item.key)[0]
if (target) {
Object.assign(target, this.cacheData.filter(item => key === item.key)[0])
delete target.editable
this.data = newData
}
},
},
mounted() {
}
}
</script>
5.最终效果
6.该功能是基于awe-dnd插件和ant design 开发完成 ,以上drag组件也可使用于其他vue框架 如iview ,使用其他框架要遵循框架具体使用情况,需要保证drag组件绑定的onChange事件触发的回调函数中返回的数据val 适用于其余框架的table规范。