需要实现表格列宽度调整,选择展示表格字段,以及显示顺序,先看效果,每次变动后保存到本地缓存中,也可以与后台配合保存到数据库,实现用户自定义表格.
1.安装vuedraggable实现拖拽
npm i vuedraggable
2.新建组件 FilterColumns.vue
我这里默认把操作列放到最后一个并且不允许编辑,如不需要可删除
<template>
<RadioGroup type="button">
<Radio title="筛选列">
<Icon type="md-list" class="showColumn" @click="modalVisible = true">
</Icon>
<Modal
title="筛选列"
v-model="modalVisible"
:mask-closable="false"
:width="800"
>
<Form ref="form" inline>
<FormItem style="width: 98%" class="showcolumns">
<CheckboxGroup v-model="selectTitles" @on-change="changeColumns">
<draggable
v-model="sortTitles"
chosenClass="active"
animation="500"
@end="changeColumns"
>
<Checkbox
v-for="(item, index) in sortTitles"
:key="index"
:label="item"
v-show="!['操作', 'undefined'].includes(item + '')"
>
<span>{{ item }}</span>
</Checkbox>
</draggable>
</CheckboxGroup>
</FormItem>
</Form>
<div slot="footer">
<Button type="text" @click="clear">重置</Button>
<Button type="text" @click="modalVisible = false">取消</Button>
<Button type="success" @click="reverseSelect">反选</Button>
</div>
</Modal>
</Radio>
</RadioGroup>
</template>
<script>
import draggable from "vuedraggable";
export default {
name: "FilterColumns",
components: { draggable },
props: {
columns: {
type: Array,
default: () => [],
},
cacheKey: {
type: String,
default: "",
},
},
data() {
return {
key: "",
modalVisible: false, // 添加或编辑显示
selectTitles: [],
sortTitles: [],
widthTitles:{
init:"0",
},
};
},
methods: {
changeColumnsWidth(v){
if(v){
this.widthTitles[v[2].title] = v[0];
this.changeColumns();
}
},
clear(){
this.removeStore(`select::${this.key}`);
this.removeStore(`sort::${this.key}`);
this.removeStore(`width::${this.key}`);
this.init();
},
init() {
//this.key = this.$route.name;
if (this.cacheKey) {
this.key = this.cacheKey;
} else {
this.key = this.$route.name;
}
this.initData();
this.changeColumns();
},
initData() {
//此处保存到本地缓存,可换成请求后台接口获取用户自定义数据
let selectTitleStr = this.getStore(`select::${this.key}`);
this.selectTitles = selectTitleStr && selectTitleStr != "[]"? JSON.parse(selectTitleStr) : [];
let sortColumsStr = this.getStore(`sort::${this.key}`);
this.sortTitles =
sortColumsStr && sortColumsStr != "[]" ? JSON.parse(sortColumsStr) : [];
let widthColumsStr = this.getStore(`width::${this.key}`);
this.widthTitles =
widthColumsStr && widthColumsStr != "{}" ? JSON.parse(widthColumsStr) : { init:"0"};
},
changeColumns() {
var that = this;
if (!!!this.sortTitles.length) {
this.sortTitles = this.columns
.map((item) => item.title)
.filter((item) => item && item.title != "操作");
}
this.columns.forEach(item => {
item.resizable = true;
if(!item.width && item.minWidth){
item.width = item.minWidth
} else if(!item.width && !item.minWidth){
item.width = 200;
}
});
if (this.widthTitles.init=="0") {
this.columns.forEach(item=>{
that.widthTitles[item.title] = item.width;
})
that.widthTitles.init = "1";
}
//如果选中标题不存在则赋予全部
if (!!!this.selectTitles.length) {
this.selectTitles = JSON.parse(JSON.stringify(this.sortTitles));
}
//此处保存到本地缓存,可换成请求后台接口,保存至数据库
this.setStore(`select::${this.key}`, JSON.stringify(this.selectTitles));
this.setStore(`sort::${this.key}`, JSON.stringify(this.sortTitles));
this.setStore(`width::${this.key}`, JSON.stringify(this.widthTitles));
let currentColumns = this.columns
.filter(
(item) =>
this.selectTitles.includes(item.title) ||
!!!item.title ||
item.title == "操作"
)
.map((item, index) => {
if (item.title !== "操作" && item.title) {
item.titleSort = this.sortTitles.findIndex(
(sortTitle) => item.title == sortTitle
);
} else if (item.title == "操作") {
item.titleSort = this.sortTitles.length;
} else {
item.titleSort = -this.sortTitles.length + index;
}
return item;
});
currentColumns.sort((a, b) => a.titleSort - b.titleSort);
currentColumns.forEach(item=>{
item.width = that.widthTitles[item.title];
})
delete currentColumns[currentColumns.length-1].width
currentColumns[currentColumns.length-1].minWidth= 162;
this.$emit("on-change", currentColumns);
},
reverseSelect() {
if (this.selectTitles.length > 0) {
this.selectTitles = [];
} else {
this.selectTitles = JSON.parse(JSON.stringify(this.sortTitles));
this.changeColumns();
}
},
},
mounted() {
this.init();
this.$nextTick(function() {
this.$on('changeCWidth', function(newWidth, oldWidth, column, event) {
this.changeColumnsWidth(newWidth, oldWidth, column, event);
});
});
},
};
</script>
<style lang="less" scoped>
.filter-columns-btn {
width: 30px;
height: 30px;
line-height: 25px;
text-align: center;
border-radius: 2px;
border: 1px solid #4383f3;
cursor: pointer;
}
</style>
3.在main.js中注册成全局组件
import FilterColumns from '@/views/my-components/FilterColumns'
Vue.component('filterColumns', FilterColumns);
4.使用方法
在合适位置(一般搜索按钮后,会显示筛选按钮)引入组件
<filterColumns
ref="fc"
:columns="columns"
@on-change="currentColumns = $event"
/>
<Table
@on-column-width-resize="$refs.fc.changeColumnsWidth(arguments)"
:columns="currentColumns"
:data="data"
ref="table"
></Table>
<script>
export default {
data() {
//可展示的字段
columns:[
{
type: "selection",
width: 35,
align: "center",
},
{
type: "index",
width: 55,
align: "center",
},
],
//需要展示的字段,设置为空数组即可
currentColumns:[],
}
}
</script>