特性
- 可以显示隐藏某一列
- 可以圈选显示隐藏所有列(禁用列不受状态影响)
- 可以拖拽列名进行前后排序
<template>
<div :class="$options.name">
<el-dropdown :show-timeout="0" :placement="`bottom`">
<el-link :underline="false" style="cursor: default"
>表格列设置
<el-tooltip
:enterable="false"
effect="dark"
:content="`可以上下拖拽改变列顺序`"
placement="top"
:transition="`none`"
>
<i class="el-icon-question"></i>
</el-tooltip>
<i class="el-icon-arrow-down"></i>
</el-link>
<el-dropdown-menu
slot="dropdown"
style="transition: none; overflow-y: auto; max-height: 400px; margin-top: 5px"
><el-dropdown-item style="padding: 0">
<el-checkbox
style="width: 100%; box-sizing: border-box; padding: 0 20px"
:indeterminate="checkedHalf"
:disabled="!tableColumns.some((v) => !v.disabled)"
v-model="checkedAll"
@change="changeCheckedAll"
@click.native.stop
>全选</el-checkbox
></el-dropdown-item
>
<el-dropdown-item
style="padding: 0"
v-for="(item, index) in tableColumns"
:key="index"
:divided="item.divided"
>
<div
:draggable="!item.disabled"
style="
box-sizing: border-box;
border: 2px dashed transparent;
border-left: none;
border-right: none;
"
@dragstart="dragstart($event, index)"
@drag="drag"
@dragend="dragend"
@dragover="dragover"
@drop="drop($event, index)"
@dragleave="dragleave"
>
<el-checkbox
style="width: 100%; box-sizing: border-box; padding: 0 20px"
:disabled="item.disabled"
v-model="item.checked"
@click.native.stop
>{{ item.label }}</el-checkbox
>
</div></el-dropdown-item
>
</el-dropdown-menu>
</el-dropdown>
<el-table :data="tableData">
<el-table-column type="selection" width="50" />
<el-table-column type="index" label="序号" width="60" />
<!-- 主要列 BEGIN---------------------------------------- -->
<el-table-column
v-for="(a, i) in tableColumns"
v-if="a.checked"
:key="i"
:prop="a.prop"
:label="a.label"
:width="a.width || `auto`"
/>
<!-- 主要列 END---------------------------------------- -->
<el-table-column label="操作" width="150">
<template slot-scope="scope">
<el-button size="mini" type="primary">修改</el-button>
<el-button size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data() {
return {
// 表格列字段----------------------------------------
checkedHalf: false,
checkedAll: false,
tableColumns: [
{ prop: "ZD1", label: "字段名称1", width: 110, checked: true, },
{ prop: "ZD2", label: "字段名称2", width: 200, checked: true, disabled: true },
{ prop: "ZD3", label: "字段名称3", width: 110, checked: true, },
{ prop: "ZD4", label: "字段名称4", width: 110 },
{ prop: "ZD5", label: "字段名称5", width: 110 },
],
// ----------------------------------------
tableData: [
{
ZD1: "字段1的值-1",
ZD2: "字段2的值-1",
ZD3: "字段3的值-1",
ZD4: "字段4的值-1",
ZD5: "字段5的值-1",
},
{
ZD1: "字段1的值-2",
ZD2: "字段2的值-2",
ZD3: "字段3的值-2",
ZD4: "字段4的值-2",
ZD5: "字段5的值-2",
},
{
ZD1: "字段1的值-3",
ZD2: "字段2的值-3",
ZD3: "字段3的值-3",
ZD4: "字段4的值-3",
ZD5: "字段5的值-3",
},
{
ZD1: "字段1的值-4",
ZD2: "字段2的值-4",
ZD3: "字段3的值-4",
ZD4: "字段4的值-4",
ZD5: "字段5的值-4",
},
{
ZD1: "字段1的值-5",
ZD2: "字段2的值-5",
ZD3: "字段3的值-5",
ZD4: "字段4的值-5",
ZD5: "字段5的值-5",
},
], //表格数据
};
},
watch: {
tableColumns: {
handler(newValue, oldValue) {
if (newValue && Object.keys(newValue).length) {
this.checkedHalf =
newValue.some((v) => v.checked) && newValue.some((v) => !v.checked); //部分选中
newValue.every((v) => v.checked) &&
((this.checkedAll = true), (this.checkedHalf = false)); //全选中
this.checkedHalf && (this.checkedAll = false); //未全选中
}
},
deep: true, //深度监听
immediate: true, //立即执行
},
},
methods: {
changeCheckedAll(checked) {
let allowItems = this.tableColumns.filter((v) => !v.disabled); //未被禁用的选项
this.checkedAll = allowItems.some((v) => !v.checked); //在未被禁用的选项中,只要有一个未勾选,点击“全选”就是全选,否者就是全不选
allowItems.forEach((v) => this.$set(v, "checked", this.checkedAll));
},
// 被拖拽物体的监听事件----------------------------------------
dragstart(e, index) {
e.dataTransfer.setData("fromIndex", index); //传递拖拽起始位置索引
},
drag(e) {
e.currentTarget.style.opacity = 0.618; //被拖拽元素透明
},
dragend(e) {
e.currentTarget.style.opacity = 1; //被拖拽元素恢复透明
},
// 放置区域的监听事件----------------------------------------
dragover(e) {
let et = e.currentTarget;
let lessThanHalf = e.offsetY < et.offsetHeight / 2; //向下拖动鼠标未超过被放置区域一半高度(如果放入物体包含很多深层级子元素,需要在拖拽过程设置子元素pointer-events: none;)
et.style.borderTopColor = lessThanHalf ? `#409EFF` : `transparent`; //上边线显示
et.style.borderBottomColor = !lessThanHalf ? `#409EFF` : `transparent`; //下边线显示
e.preventDefault();
},
drop(e, index) {
let et = e.currentTarget;
et.style.borderColor = `transparent`;
let lessThanHalf = e.offsetY < et.offsetHeight / 2; //向下拖动鼠标未超过被放置区域一半高度(如果放入物体包含很多深层级子元素,需要在拖拽过程设置子元素pointer-events: none;)
let fromIndex = e.dataTransfer.getData("fromIndex"); //拖拽起始位置索引
let toIndex = index; //拖拽到的目标位置索引
if (fromIndex == toIndex) return; //一样的位置就不改变顺序了
toIndex =
fromIndex < toIndex
? lessThanHalf
? index - 1
: index
: lessThanHalf
? index
: index + 1; //拖拽到不同的目标位置索引(注意细节:从下往上拖拽 和 从上往下 拖拽索引的大小不一样)
this.$g.array.moveArrayElement(this.tableColumns, fromIndex, toIndex); //移动目标元素
},
dragleave(e) {
e.currentTarget.style.borderColor = `transparent`; //清空边框线
},
},
};
</script>