ElementUI实现el-table列的显示与隐藏和列拖拽(RuoYi分离版)
ElementUI实现el-table列的显示与隐藏和列拖拽(RuoYi分离版)
显示隐藏步骤思路:
一、table要实现v-for循环添加列的操作
二、给列添加v-if属性 方法返回当前列是否显示隐藏
①在RightToolBar添加列显示隐藏的图标控件
<template>
<div class="top-right-btn">
<el-row>
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top">
<el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
</el-tooltip>
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
<el-button size="mini" circle icon="el-icon-refresh" @click="refresh()" />
</el-tooltip>
<el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="columns!=undefined">
<el-dropdown trigger="click" :hide-on-click="false" style="padding-left: 12px">
<el-button size="mini" circle icon="el-icon-menu"/>
<el-dropdown-menu slot="dropdown">
<template v-for="item in columns">
<el-dropdown-item><el-checkbox :checked="item.isShow" @change="monitorChange($event,item.label)" :label="item.label"></el-checkbox></el-dropdown-item>
</template>
</el-dropdown-menu>
</el-dropdown>
</el-tooltip>
</el-row>
<el-dialog :title="title" :visible.sync="open" append-to-body>
<el-transfer
:titles="['显示', '隐藏']"
v-model="value"
:data="columns"
@change="dataChange"
></el-transfer>
</el-dialog>
</div>
</template>
<script>
export default {
name: "RightToolbar",
data() {
return {
// 显隐数据
value: [],
// 弹出层标题
title: "显示/隐藏",
// 是否显示弹出层
open: false,
};
},
props: {
showSearch: {
type: Boolean,
default: true,
},
columns: {
type: Array,
},
},
created() {
},
methods: {
// 搜索
toggleSearch() {
this.$emit("update:showSearch", !this.showSearch);
},
// 刷新
refresh() {
this.$emit("queryTable");
},
// 右侧列表元素变化
dataChange(data) {
for (var item in this.columns) {
const key = this.columns[item].key;
this.columns[item].visible = !data.includes(key);
}
},
monitorChange(event,label){
this.columns.filter(item=>item.label==label)[0].isShow=event
}
},
};
</script>
<style lang="scss" scoped>
::v-deep .el-transfer__button {
border-radius: 50%;
padding: 12px;
display: block;
margin-left: 0px;
}
::v-deep .el-transfer__button:first-child {
margin-bottom: 10px;
}
</style>
下列菜单用的是checkBox组 成品效果就是这样的
具体两个父子控件怎么传递数据,这里不过多讲解。
下面是表格的主要代码
<right-toolbar
:showSearch.sync="showSearch"
:columns="allTableLabel"
@queryTable="getList"
></right-toolbar>
</el-row>
<el-table
v-loading="loading"
:data="purchaseList"
row-key="id"
border
ref="purchaseTable"
@selection-change="handleSelectionChange"
>
<template
v-for="column in tableColumns">
<el-table-column
v-if="judgeIsShow(column.label)"
:key="column.id"
:prop="column.prop"
:class-name="column.isDrag"
:label="column.label"
:align="column.align"
:type="column.type"
:width="column.width"
>
<template v-if="column.scope=='scope'" scope="scope">
<span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
</template>
<template v-else-if="column.scope=='slot-scope'" slot-scope="scope">
{{scope.row.contractNum}}/{{getUnit(scope.row.quantityUnit)}}
</template>
<template v-else-if="column.scope=='ClientTag'" slot-scope="scope">
<ClientTag :value="scope.row.contractId" :flag="flag" :view="table"/>
</template>
</el-table-column>
</template>
</el-table>
下边的定义的数据和方法的代码
//elementui测试
tableColumns:[
{id:"0",type:"selection",width:"55",align:"center"},
{id:"1",type:"index",label:"序号",align:"center",scope:"scope"},
{id:"2",label:"采购合同号",prop:"contractNo",align:"center",isDrag:"drag"},
{id:"3",label:"原产国",prop:"countryName",align:"center",isDrag:"drag"},
{id:"4",label:"产品",prop:"productName",align:"center",isDrag:"drag",scope:"ClientTag"},
{id:"5",label:"合同总数量",prop:"contractNum,quantityUnit",isDrag:"drag",align:"center",scope: "slot-scope"},
{id:"6",label:"合同总金额",prop:"contractPrice",align:"center"},
],
//elementui的table所有的表头数据
allTableLabel:[],
//把列的显示和隐藏 存Cookie
setTableShowToCookie(){
let label="";
let isShow="";
let labelArr=[];
let isShowArr=[];
this.allTableLabel.forEach((item)=>{
labelArr.push(item.label)
isShowArr.push(item.isShow);
})
label=labelArr.join(',')
isShow=isShowArr.join(',')
Cookies.set("purchaseTableLabel",label)
Cookies.set("purchaseTableIsShow",isShow)
},
getTableShowOfCookie(){
let label=Cookies.get("purchaseTableLabel");
let isShow=Cookies.get("purchaseTableIsShow");
console.log(label)
if (label==undefined){
this.allTableLabel=[
{label:"序号",isShow:true},
{label:"采购合同号",isShow:true},
{label:"原产国",isShow:true},
{label:"产品",isShow:true},
{label:"合同总数量",isShow:true},
{label:"合同总金额",isShow:true},
];
}else{
let labelArr=label.split(",");
let isShowArr=isShow.split(",");
let len=labelArr.length;
console.log("长度为"+len)
for (let i=0;i<len;i++){
this.allTableLabel.push({label:labelArr[i],isShow:isShowArr[i]=="true"?true:false});
}
}
},
//判断是否显示列
judgeIsShow(column){
let exist=this.allTableLabel.filter(item=> item.label==column);
let isShow;
if (exist.length==0){
isShow=true
}else{
isShow= exist[0].isShow;
}
return isShow;
},
主要逻辑就是通过改变checkBox的选中和取消同步列的显示和隐藏 这个地方是根据两个数组中的label属性进行判断的 两者的label的值要保持一致。
效果图如下:
列拖拽的步骤思路:
一、要借助第三方插件Sortable.js
二、主要是改变table遍历的列的顺序
<el-table
v-loading="loading"
:data="purchaseList"
row-key="id"
border
ref="purchaseTable"
@selection-change="handleSelectionChange"
>
<template
v-for="column in tableColumns">
<el-table-column
v-if="judgeIsShow(column.label)"
:key="column.id"
:prop="column.prop"
:class-name="column.isDrag"
:label="column.label"
:align="column.align"
:type="column.type"
:width="column.width"
>
<template v-if="column.scope=='scope'" scope="scope">
<span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
</template>
<template v-else-if="column.scope=='slot-scope'" slot-scope="scope">
{{scope.row.contractNum}}/{{getUnit(scope.row.quantityUnit)}}
</template>
<template v-else-if="column.scope=='ClientTag'" slot-scope="scope">
<ClientTag :value="scope.row.contractId" :flag="flag" :view="table"/>
</template>
</el-table-column>
</template>
</el-table>
import Sortable from "sortablejs";
import draggable from "vuedraggable";
export default {
name: "Purchase",
components: {
draggable,
Sortable,
},
data() {
return {
table:"productTable",
flag:"contractProducts",
//elementui测试
tableColumns:[
{id:"0",type:"selection",width:"55",align:"center"},
{id:"1",type:"index",label:"序号",align:"center",scope:"scope"},
{id:"2",label:"采购合同号",prop:"contractNo",align:"center",isDrag:"drag"},
{id:"3",label:"原产国",prop:"countryName",align:"center",isDrag:"drag"},
{id:"4",label:"产品",prop:"productName",align:"center",isDrag:"drag",scope:"ClientTag"},
{id:"5",label:"合同总数量",prop:"contractNum,quantityUnit",isDrag:"drag",align:"center",scope: "slot-scope"},
{id:"6",label:"合同总金额",prop:"contractPrice",align:"center"},
],
//elementui的table所有的表头数据
allTableLabel:[],
mounted() {
this.columnDrop();
},
methods: {
//列拖拽
columnDrop(){
//const wrapperTr = document.querySelector('.el-table__header-wrapper tr')
const wrapperTr = this.$refs.purchaseTable.$el.querySelector('.el-table__header-wrapper tr');
const that=this;
this.sortable = Sortable.create(wrapperTr, {
animation: 180,
delay: 30,
draggable:".drag",
onEnd: evt => {
if (this.tableColumns[evt.newIndex].isDrag!=undefined) {
const oldItem = this.tableColumns[evt.oldIndex]
this.tableColumns.splice(evt.oldIndex, 1);
this.tableColumns.splice(evt.newIndex, 0, oldItem)
//改变两个列的id属性之后 表格的数据才进行跟新
this.tableColumns[evt.oldIndex].id=parseTime(new Date(), "{y}{m}{d}{h}{i}{s}")+"1"
this.tableColumns[evt.newIndex].id=parseTime(new Date(), "{y}{m}{d}{h}{i}{s}")+"2"
}else{
}
},
});
},
}
效果图如下显示:
到此为止分别引用的时候是没问题的。
但是两者整合的时候有BUG
主要原因是因为拖拽的是显示的列,而重排的是全部的列,同时evt.oldIndex和evt.newIndex是显示列拖拽的column的index 这个地方用splice方法重排所有的column的index 排序的时候就出现乱排、不排的现象。
解决思路:
获得拖拽列的两个列的label 然后遍历全部的列 要是label相等的就返回全部列其中两个相等label列的下标 然后重排这两个列就行。
具体代码优化如下:
//列拖拽
columnDrop(){
//const wrapperTr = document.querySelector('.el-table__header-wrapper tr')
const wrapperTr = this.$refs.purchaseTable.$el.querySelector('.el-table__header-wrapper tr');
const tableColumn=this.$refs.purchaseTable.columns;
let oldLabel;
let newLabel;
let oldIndex;
let newIndex;
let count=0;
const that=this;
this.sortable = Sortable.create(wrapperTr, {
animation: 180,
delay: 30,
draggable:".drag",
onEnd: evt => {
if (this.tableColumns[evt.newIndex].isDrag!=undefined) {
oldLabel=this.$refs.purchaseTable.columns[evt.oldIndex].label;
newLabel=this.$refs.purchaseTable.columns[evt.newIndex].label;
for (let i=0;i<that.tableColumns.length;i++){
if (that.tableColumns[i].label!=undefined&&that.tableColumns[i].label==newLabel)
newIndex=i;
};
for (let i=0;i<that.tableColumns.length;i++){
if (that.tableColumns[i].label!=undefined&&that.tableColumns[i].label==oldLabel)
oldIndex=i;
}
const oldItem = this.tableColumns[oldIndex]
this.tableColumns.splice(oldIndex, 1);
this.tableColumns.splice(newIndex, 0, oldItem)
this.tableColumns.forEach((item)=>{
if(item.label==newLabel||item.label==oldLabel){
item.id=parseTime(new Date(), "{y}{m}{d}{h}{i}{s}") + (++count)
console.log(item.label)
}
})
}else{
}
},
});
},
整体效果图如下:
以上代码只是粘贴了主要部分,有什么好的方法欢迎交流
更多推荐
所有评论(0)