参考:在 Element-UI 的 Table 组件上添加列拖拽效果 - Wise.Wrong - 博客园
1. css: dragTable.css
@charset "UTF-8";
.w-table{
height: 100%;
width: 100%;
float: left;
}
/* 拖动过程中,鼠标显示样式 */
.w-table_moving .el-table th .thead-cell{
cursor: move ;
}
.w-table_moving .el-table__fixed, .w-table_moving .is-hidden{
cursor: not-allowed !important;
}
.w-table .thead-cell{
display: inline-flex;
flex-direction: column;
align-items: center;
width: auto;
max-height: 23px;
vertical-align: middle;
overflow: initial;
position: relative;
}
/* 拖动列的颜色 */
.w-table .el-table .darg_start {
background-color: #F1F3F4 !important;
}
.darg_active_left , .darg_active_right {
border-left: 2px dotted #cdcfd0 !important;
z-index: 999;
}
2. 封装组件: dragTable.vue
<template>
<div class="w-table" :class="{'w-table_moving': dragState.dragging}">
<el-table :data="data"
:row-key="option.rowKey"
:class="option.class"
:stripe="option.stripe"
:border="option.border"
:height="option.height"
:max-height="option.maxHeight"
highlight-current-row
:style="{ width: parseInt(option.width)+'px' }" :cell-class-name="cellClassName"
:header-cell-class-name="headerCellClassName"
@sort-change="option.sortChange"
:ref="option.rowKey"
:default-sort = "option.defaultSort"
>
<slot name="fixed"></slot>
<template v-for="(col, index) in tableHeader">
<el-table-column :label="col.label" :key="index" :prop="col.prop" :width="col.width" v-if="col.useTemplate==true">
<template slot-scope="scope">
<span v-html=col.useTemplateRes(scope.row)></span>
</template>
</el-table-column>
<el-table-column v-else
:key="index"
:prop="col.prop"
:label="col.label"
:width="col.width"
:min-width="col.minWidth"
:type="col.type"
:sortable="col.sortable"
:header-align="col.headerAlign"
:align="col.align"
:column-key="index.toString()"
:render-header="renderHeader"
show-overflow-tooltip
:formatter="col.formatter"
>
</el-table-column>
</template>
<!--<el-table-column v-for="(col, index) in tableHeader" :key="index"
:prop="col.prop"
:label="col.label"
:width="col.width"
:min-width="col.minWidth"
:type="col.type"
:sortable="col.sortable"
:header-align="col.headerAlign"
:align="col.align"
:column-key="index.toString()"
:render-header="renderHeader"
show-overflow-tooltip
:formatter="col.formatter"
>
</el-table-column>-->
</el-table>
</div>
</template>
<script>
import Sortable from 'sortablejs'
export default {
name: "",
data () {
return {
tableHeader: this.header,
dragState: {
start: -9, // 起始元素的 index
end: -9, // 移动鼠标时所覆盖的元素 index
dragging: false, // 是否正在拖动
direction: undefined // 拖动方向
}
}
},
props: {
data: {
default: function () {
return []
},
type: Array
},
header: {
default: function () {
return []
},
type: Array
},
option: {
default: function () {
return {}
},
type: Object
}
},
mounted() {
},
watch: {
header (val, oldVal) {
this.tableHeader = val
}
},
methods: {
renderHeader (createElement, {column}) {
return createElement(
'div', {
'class': ['thead-cell'],
on: {
mousedown: ($event) => { this.handleMouseDown($event, column) },
mousemove: ($event) => { this.handleMouseMove($event, column) }
}
}, [
// 添加 <a> 用于显示表头 label
createElement('span', column.label),
// 添加一个空标签用于显示拖动动画
createElement('span', {
'class': ['virtual']
})
])
},
// 按下鼠标开始拖动
handleMouseDown (e, column) {
this.dragState.dragging = true
this.dragState.start = parseInt(column.columnKey)
// 给拖动时的虚拟容器添加宽高
let table = document.getElementsByClassName('w-table')[0]
let virtual = document.getElementsByClassName('virtual')
for (let item of virtual) {
item.style.height = table.clientHeight - 1 + 'px'
// item.style.width = item.parentElement.parentElement.clientWidth + 'px'
item.style.width = item.parentElement.clientWidth + 'px'
}
document.addEventListener('mouseup', this.handleMouseUp);
},
// 鼠标放开结束拖动
handleMouseUp () {
this.dragColumn(this.dragState)
// 初始化拖动状态
this.dragState = {
start: -9,
end: -9,
dragging: false,
direction: undefined
}
document.removeEventListener('mouseup', this.handleMouseUp);
},
// 拖动中
handleMouseMove (e, column) {
if (this.dragState.dragging) {
let index = parseInt(column.columnKey) // 记录起始列
if (index - this.dragState.start !== 0) {
this.dragState.direction = index - this.dragState.start < 0 ? 'left' : 'right' // 判断拖动方向
this.dragState.end = parseInt(column.columnKey)
} else {
this.dragState.direction = undefined
}
} else {
return false
}
},
// 拖动易位
dragColumn ({start, end, direction}) {
let tempData = []
let left = direction === 'left'
let min = left ? end : start - 1
let max = left ? start + 1 : end
for (let i = 0; i < this.tableHeader.length; i++) {
if (i === end) {
tempData.push(this.tableHeader[start])
} else if (i > min && i < max) {
tempData.push(this.tableHeader[ left ? i - 1 : i + 1 ])
} else {
tempData.push(this.tableHeader[i])
}
}
this.tableHeader = tempData
},
/* this.option.fixColNum 是固定列的数量 */
/*动态样式:在拖动过程中,通过 mousemove 事件,改变当前列的表头状态 然后借助 headerCellClassName, cellClassName 动态修改单元格 class -----begin */
headerCellClassName ({column, columnIndex}) {
let active = columnIndex - this.option.fixColNum === this.dragState.end ? `darg_active_${this.dragState.direction}` : ''
let start = columnIndex - this.option.fixColNum === this.dragState.start ? `darg_start` : ''
return `${active} ${start}`
},
cellClassName ({column, columnIndex}) {
// return (columnIndex - this.option.fixColNum === this.dragState.start ? `darg_start` : '')
//fuhm 改
let active = columnIndex - this.option.fixColNum === this.dragState.end ? `darg_active_${this.dragState.direction}` : ''
let start = columnIndex - this.option.fixColNum === this.dragState.start ? `darg_start` : ''
return `${active} ${start}`
},
/*动态样式:在拖动过程中,通过 mousemove 事件,改变当前列的表头状态 然后借助 headerCellClassName, cellClassName 动态修改单元格 class -----end */
clearSort(){
let ref = this.option.rowKey;
this.$refs[ref].clearSort();
},
},
}
</script>
<style >
@import '~@/assets/css/dragTable.css';
</style>
3. 调用封装组件
<template>
<div>
<wTable :data="WarnResTable_Data_SS" :header="tableHeaderSS" :option="tableOptionSS">
<el-table-column
type="index"
slot="fixed"
fixed
prop=""
label="序号"
align="center"
width="60"
>
</el-table-column>
<el-table-column
label="操作"
slot="fixed"
fixed
prop=""
width="95"
align="center">
<template slot-scope="scope">
<el-button
size="mini"
@click="lookDetails(scope.$index, scope.row)">查看
</el-button>
</template>
</el-table-column>
</wTable>
</div>
</template>
<script>
import wTable from '../../components/dragTable/dragTable'
export default {
name: 'Table',
data () {
return {
tableOptionSS: {
fixColNum:2,
border: true,
stripe: true,
ref:'WarnResSSTable',
class:'pms-table',
maxHeight: "100%",
height: "100%",
sortChange:this.changeTableSortSS
},
tableHeaderSS: [
{
label: '地市名称',
prop: 'dsmc',
sortable: true,
align:'center',
width:'200',
},
{
label: '运维单位',
prop: 'ywdw',
align:'center',
width:'200',
},
{
label: '变电站',
prop: 'bdzmc',
align:'center',
width:'170',
},
{
label: '设备名称',
prop: 'sbmc',
sortable: true,
align:'center',
width:'150',
},
{
label: '预警参数',
prop: 'yjcs',
align:'center',
width:'150',
},
{
label: '预警类型',
prop: 'yjlx',
align:'center',
width:'140',
},
{
label: '首次预警时间',
prop: 'scyjsj',
sortable:true,
align:'center',
width:'160',
formatter:this.formatTime
},
{
label: '更新数据时间',
prop: 'dqyjsj',
sortable:true,
align:'center',
width:'160',
formatter:this.formatTime
},
{
label: '预警描述',
prop: 'yjgz',
align:'center',
width:'170',
},
{
label: '设备类型',
prop: 'sblx',
sortable:true,
align:'center',
width:'140',
},
{
label: '电压等级',
prop: 'dydjid',
sortable:true,
align:'center',
width:'120',
formatter:this.formatVoltageLevel
}
],
WarnResTable_Data_SS:[
{dsmc:'dsmc1',sbmc:'sbmc1',dydjid:'hhhhh1'},
{dsmc:'dsmc2',sbmc:'sbmc2',dydjid:'hhhhh2'},
{dsmc:'dsmc3',sbmc:'sbmc3',dydjid:'hhhhh3'}
],
}
},
methods: {
handleNameSort () {
console.log('handleNameSort')
},
formatVoltageLevel: function (row, column) {
let val = row[column.property];
if (val == undefined) {
return "";
}
console.log('val ')
return '5555'
},
changeTableSortSS(column){
console.log(' sortHandle column',column)
},
formatTime: function (row, column) {
let date = row[column.property];
if (date == undefined) {
return "";
}
return date?moment(new Date(date)).format('YYYY-MM-DD HH:MM:SS'):'';
},
formatVoltageLevel: function (row, column) {
let val = row[column.property];
if (val == undefined) {
return "";
}
return val+'kV'
},
},
components: {
wTable
}
}
</script>