1 参考其他文章
Vue+ElementUI 实现 动态调整表格列 显示隐藏&显示顺序
2 具体实现
2.1 将列拖拽功能封装到通用表格动态列组件里
关于表格动态列组件的具体代码,可以看我的另一篇博客:Vue - 基于Element UI封装一个表格动态列组件。
2.2 实现思路
- 引入sortablejs插件;
- 获取显示的表格列数据;
- 考虑动态列之前的列,如下图,Sortable获取的index是对应整个表格的列数据index,动态列数据需要减去emty;
- 获取原来位置下标和新位置下标(考虑动态列表包含visible为false数据,作查找位置(findIndex)后找到其index下标);
- 删除原来位置列数据、在新位置插入该列数据;
- 使用时需要获取表格Dom元素,当一个页面有多个表格的情况,需要加一个类去获取到对应的表格Dom元素,故传入tableSign变量。
2.3 列拖拽具体代码
import Sortable from 'sortablejs'
export default {
props: {
// 非必传,只有存在多个表格时,该参数作为表格的唯一标识,主要用于拖拽
tableSign: {
type: String,
default: null
},
// 所有的列字段,用于拖拽
schemas: {
type: Array,
default: () => {
return []
}
},
// 不在schemas内,并且在动态列之前的列数
empty: {
type: Number,
default: 0
},
},
mounted() {
// 表格拖拽方法
if (this.schemas.length > 0) {
this.columnDrop()
}
},
methods: {
/**
* 列拖拽
*/
columnDrop() {
// 页面多个表格 取到对应表格dom元素
let wrapperClass = '.el-table__header-wrapper'
if (this.tableSign) {
const elClass = this.$parent.$el.getAttribute('class')
if (!elClass.includes(this.tableSign)) {
this.$parent.$el.setAttribute('class', `${elClass} ${this.tableSign}`)
}
wrapperClass = `.${this.tableSign} ${wrapperClass}`
}
const wrapperTr = document.querySelector(`${wrapperClass} tr`)
this.sortable = Sortable.create(wrapperTr, {
animation: 100, // 过渡动画
delay: 0, // 延迟多久可以拖动
onEnd: (evt) => {
if (evt.oldIndex === evt.newIndex) return
const overviewColumns = [...this.schemas]
const visbleColumns = overviewColumns.filter((v) => v.visible) // 显示的列
const empty = this.empty // 不在schemas内,并且在动态列之前的列数
// 注意:动态列表包含visible为false数据,需要进行特殊查找位置处理
const oldItem = visbleColumns[evt.oldIndex - empty]
const newItem = visbleColumns[evt.newIndex - empty]
const realOldIndex = overviewColumns.findIndex(
(item) => item.prop === oldItem.prop
)
const realNewIndex = overviewColumns.findIndex(
(item) => item.prop === newItem.prop
)
overviewColumns.splice(realOldIndex, 1) // 删除原来位置的数据
overviewColumns.splice(realNewIndex, 0, oldItem) // 在新的位置插入该数据
this.$emit('changeColumn', overviewColumns)
}
})
}
}
}
2.4 在页面中使用
<el-table
ref="allListTableRef"
v-loading="tableLoading"
size="mini"
:data="infoList"
height="430px"
:cell-style="cellStyle"
@sort-change="handleSortChange"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<DynamicColumn
v-for="(ite, index) in overviewColumns"
:key="index"
:item="ite"
:empty="1"
:data-list="infoList"
table-sign="all-list"
:schemas="overviewColumns"
@changeColumn="(cols)=>{overviewColumns=cols;}"
/>
<el-table-column
:label="$t('operate')"
prop="operate"
align="center"
width="200"
fixed="right"
>
<template slot-scope="scope">
<el-button
v-hasPermi="['investmentDecision:etfPool:etfList:index:detail']"
type="text"
size="mini"
icon="el-icon-info"
@click="goDetail(scope.row)"
>{{ $t("viewDetails") }}</el-button>
</template>
</el-table-column>
</el-table>
// 动态列
overviewColumns: this.$columns.getColumns('etfPool_list_overview'),
// 表格数据
infoList: [],