项目场景:
VUE+Element 实现el-table动态设置表头(可拖拽)
问题描述:
由于Element组件不支持动态拖拽设置表头,所以使用
awe-dnd
插件实现拖拽效果
实现方法:
安装依赖
npm install awe-dnd --save
全局注册或局部注册
1、全局注册
- 在main.js文件中
import VueDND from 'awe-dnd';
// 注册-拖拽组件
Vue.use(VueDND);
2、局部注册(页面内注册)
import Vue from 'vue'
import VueDND from 'awe-dnd'
Vue.use(VueDND)
页面使用
1、HTML
<template>
<div class="table-box">
<el-table
v-loading="loading"
:data="tableData"
style="width: 100%"
:header-cell-style="{
background: '#FAFAFA',
color: '#000000',
'font-family': 'Source Han Sans CN',
'font-size': '14px',
'font-weight': '400'
}"
>
<!-- checkedTitle -->
<el-table-column
v-for="(title, titleIndex) in checkedTitleList"
:key="titleIndex"
:prop="title.column"
:label="title.text"
width="180"
:sortable="title.sortable"
>
<template slot-scope="{ row }">
<span>11</span>
</template>
</el-table-column>
<el-table-column
label="操 作"
width="260"
fixed="right"
class-name="small-padding fixed-width"
>
<template slot-scope="{ row }">
<div class="level buttons" style="padding: 0 5px">
<div
v-permission="{ action: 'auxiliary.plan:update' }"
class="details-btn"
@click="handleUpdate(row)"
>
编辑
</div>
</div>
</template>
</el-table-column>
</el-table>
<el-popover
v-model="visibleAllTitle"
placement="bottom"
width="200"
trigger="manual"
popper-class="select-sort-title-popover"
>
<div class="select-sort-title">
<p class="custom-column">自定义列</p>
<p class="sorting">勾选需要显示的列,拖动列名进行排序。</p>
<el-checkbox-group
v-model="checkedTitle"
@change="setTableHeader"
>
<el-checkbox
v-for="title in allTitleList"
:key="title"
v-dragging="{
item: title,
list: allTitleList,
group: 'title'
}"
:label="title"
>{{ title }}</el-checkbox>
</el-checkbox-group>
</div>
<i
slot="reference"
class="el-icon-setting"
@click="visibleAllTitle = !visibleAllTitle"
/>
</el-popover>
</div>
</template>
2、javascript
注意:由于
el-checkbox-group
的v-model
没办法绑定一个对象,会导致给不了默认值,所以复选框绑定的是字符串数组,选择或拖拽之后使用数组过滤出对应的title
列表
<script>
import lodash from 'lodash'
import Vue from 'vue'
import VueDND from 'awe-dnd'
Vue.use(VueDND)
const allTitleText = [
'表头1',
'表头2',
'表头3',
'表头4',
'表头5',
'表头6',
'表头7',
'表头8',
'表头9',
'表头10'
]
const allTitleListClone = [
{
text: '表头1',
column: 'orderNumber',
sortable: true
},
{
text: '表头2',
column: 'materialCode',
sortable: false
},
{
text: '表头3',
column: 'workshopName',
sortable: false
},
{ text: '表头4', column: 'type', sortable: false },
{ text: '表头5', column: 'planNum', sortable: false },
{
text: '表头6',
column: 'planCompleteTime',
sortable: false
},
{ text: '表头7', column: 'deliveryDate', sortable: false },
{ text: '表头8', column: 'orderDate', sortable: false },
{
text: '表头9',
column: 'currentInventory',
sortable: false
},
{ text: '表头10', column: 'isfully', sortable: false }
]
export default {
name: 'AuxiliaryPlan',
data() {
return {
tableData: [{}, {}],
// 设置表头
visibleAllTitle: false,
checkedTitle: [],
checkedTitleList: lodash.cloneDeep(allTitleListClone),
allTitleList: lodash.cloneDeep(allTitleText),
draggedList: lodash.cloneDeep(allTitleText),
}
},
mounted() {
this.dropEvent()
this.checkedTitle = lodash.cloneDeep(allTitleText)
},
methods: {
getList() {},
// 拖拽设置表头
/**
* @description:拖拽事件,选中的checkedCities 根据拖拽的list 的顺序排序
* @param {*}
* @return {*}
*/
dropEvent() {
this.$dragging.$on('dragged', ({ value }) => {
this.draggedList = value.list
this.filterCheckedTitleList()
})
},
setTableHeader() {
this.filterCheckedTitleList()
},
filterCheckedTitleList() {
this.checkedTitle.sort((a, b) => {
return this.draggedList.indexOf(a) - this.draggedList.indexOf(b)
})
const tempList = lodash.cloneDeep(this.checkedTitle)
allTitleListClone.forEach(title => {
const index = this.checkedTitle.findIndex(item => title.text === item)
if (index !== -1) {
tempList[index] = title
}
})
this.checkedTitleList = tempList
},
}
}
</script>
3、CSS
注意:由于使用了
el-popover
弹出框,需要在body内去全局修改样式才会生效,避免更改到其他地方,需要定义一个唯一的class
,el-popover
需要使用popper-class
指定对应的class
<style lang="scss" scoped>
.table-box {
position: relative;
.el-icon-setting {
position: absolute;
right: 20px;
top: 16px;
z-index: 9;
}
}
</style>
.select-sort-title-popover {
background: #ffffff;
border: 1px solid #1890ff;
box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
padding: 20px;
width: 220px !important;
.select-sort-title {
font-size: 14px;
font-family: Source Han Sans CN;
font-weight: 400;
p {
width: 100%;
margin: 0;
}
.custom-column {
color: #333333;
margin-bottom: 12px;
}
.sorting {
font-size: 10px;
transform: scale(0.8);
color: #999999;
margin-left: -18px;
width: 122%;
}
.el-checkbox {
line-height: 30px;
.el-checkbox__label {
font-size: 12px;
padding: 0 10px 0 5px;
margin-left: 10px;
}
}
.is-checked {
.el-checkbox__label {
background: #E7F4FF;
}
}
}
.popper__arrow {
border-bottom-color: #1890ff !important;
}
}
拖拽的关键代码
v-dragging="{
item: title,
list: allTitleList,
group: 'title'
}"
- 页面拖拽触发的方法
dropEvent() {
this.$dragging.$on('dragged', ({ value }) => {
this.draggedList = value.list
this.filterCheckedTitleList()
})
},
filterCheckedTitleList() {
this.checkedTitle.sort((a, b) => {
return this.draggedList.indexOf(a) - this.draggedList.indexOf(b)
})
const tempList = lodash.cloneDeep(this.checkedTitle)
allTitleListClone.forEach(title => {
const index = this.checkedTitle.findIndex(item => title.text === item)
console.log(index, 'index')
if (index !== -1) {
tempList[index] = title
}
})
this.checkedTitleList = tempList
},
效果图
- 拖拽前
- 拖拽后