最近在使用element+table组件开发后台过程中,接到一个需求,给所有表格加上列筛选功能,按大家正常的思路;肯定是每个页面加一下,通过v-if/v-show控制一下列的显示隐藏。
我这里的实现是统一处理,不管你有几个列,前提是有封装过el-tabel组件,所有表格都用了它,比如以下代码:(这个是我修改之前的代码)
<template>
<div>
<el-table
element-loading-text="加载中"
:row-key='rowKey'
:expand-row-keys="expandRowKeys"
@expand-change="expandChange"
@selection-change="selectionChange"
fit
highlight-current-row
header-cell-class-name="global_table_header"
@sort-change='sort'
:data="tableData"
:border="border"
v-loading="loading"
class="global_table">
<slot />
</el-table>
<div class="global_table_pagination">
<el-pagination
@size-change="handleSizeChange"
v-if="pages"
background
layout="total, prev, pager, next, jumper"
:total="pages"
:page-sizes="[1, 3, 5, 8]"
:page-size="pageSize"
:current-page="currentPage"
@current-change="changePage">
</el-pagination>
</div>
</div>
</template>
<script lang="ts">
import {Vue, Prop, Component} from 'vue-property-decorator'
@Component
export default class extends Vue {
@Prop({ required: true }) private tableData: any
@Prop({ default: false }) private loading?: boolean
@Prop({ required: false }) private pages?: number
@Prop({ default: 10 }) private pageSize?: number
@Prop({ default: 1 }) private currentPage?: number
@Prop({ default: false }) private border?: boolean
@Prop({ required: false }) private rowKey?: any
@Prop({ required: false }) private expandRowKeys?: any[]
protected changePage(page: number) {
this.$emit('changePage', page)
}
protected sort(value: any) {
this.$emit('sort', value)
}
protected expandChange(row: any, expandedRows: any) {
this.$emit('expandChange', row, expandedRows)
}
protected selectionChange(val: any[]) {
this.$emit('selectionChange', val)
}
protected handleSizeChange(val:any) {
console.log(`每页 ${val} 条`);
this.pageSize = val; //动态改变
}
protected handleCurrentChange(val:any) {
console.log(`当前页: ${val}`);
this.currentPage = val;
}
}
</script>
<style lang="scss" scoped>
</style>
然后在页面调用,代码如下:
<g-table :table-data="tableData">
<el-table-column></el-table-column>
...
</g-table>
import GTable from "@/components/Table/index.vue";
@Component({
components: {
GTable
},
})
当我要给所有表格,增加列筛选功能时,还是有一点难度的,具体过程就不描述了,反正保持原有排序、翻页、搜索等功能的正常使用,见代码注释把:
<template>
<div>
<i @click="cellDialog = true" class="el-icon-set-up setting"></i>
<g-dialog width="450px" @close="cellDialog = false" :show="cellDialog" title="筛选列">
<div style="margin-top:-20px">
<div style="margin-bottom:5px">
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
</div>
<div>
<el-checkbox-group @change="handleCheckedCitiesChange" v-model="checkList">
<el-checkbox class="column_label" :label="index" v-for="(item,index) in columnsList" :key="index">{{item.componentOptions.propsData.label?item.componentOptions.propsData.label:'第'+(index+1)+'列'}}</el-checkbox>
</el-checkbox-group>
</div>
<div class="global_dialog_btn">
<el-button @click="cellDialog = false">取消</el-button>
<el-button type="primary" @click="setTable()">保存</el-button>
</div>
</div>
</g-dialog>
<el-table v-if="isTable" v-loading="loading" :default-sort="sort_default" element-loading-text="加载中" :row-key='rowKey' :expand-row-keys="expandRowKeys" @expand-change="expandChange" @selection-change="selectionChange" fit highlight-current-row header-cell-class-name="global_table_header" @sort-change='sort' :data="tableData" :border="border" class="global_table">
<slot v-if="!isDefault" name="diy" />
<slot v-else />
</el-table>
<div class="global_table_pagination">
<el-pagination @size-change="handleSizeChange" v-if="pages" background layout="total, prev, pager, next, jumper" :total="pages" :page-sizes="[1, 3, 5, 8]" :page-size="pageSize" :current-page="currentPage" @current-change="changePage">
</el-pagination>
</div>
</div>
</template>
<script lang="ts">
import { Vue, Prop, Component, Watch } from "vue-property-decorator";
import GDialog from "@/components/Dialog/index.vue";
import { set } from "js-cookie";
@Component({
components: {
GDialog,
},
})
export default class extends Vue {
@Prop({ required: true }) private tableData: any;
@Prop({ default: false }) private loading?: boolean;
@Prop({ required: false }) private pages?: number;
@Prop({ default: 10 }) private pageSize?: number;
@Prop({ default: 1 }) private currentPage?: number;
@Prop({ default: false }) private border?: boolean;
@Prop({ required: false }) private rowKey?: any;
@Prop({ required: false }) private expandRowKeys?: any[];
protected changePage(page: number) {
this.$emit("changePage", page);
}
protected sort(value: any) {
this.$emit("sort", value);
}
protected expandChange(row: any, expandedRows: any) {
this.$emit("expandChange", row, expandedRows);
}
protected selectionChange(val: any[]) {
this.$emit("selectionChange", val);
}
protected handleSizeChange(val: any) {
console.log(`每页 ${val} 条`);
this.pageSize = val; //动态改变
}
protected handleCurrentChange(val: any) {
console.log(`当前页: ${val}`);
this.currentPage = val;
}
beforeUpdate(){
this.setSlot()
}
///////////////////////表格筛选/////////////////////
//全选
checkAll = false;
isIndeterminate = true;
//是否渲染表格
isTable = true;
//是否显示筛选器
cellDialog = false;
//已选中筛选项
checkList: any = new Array();
//所有列
columnsList: any = new Array();
//是否默认
isDefault = true;
//当前列
_default: any = new Array();
//排序继承
sort_default = { prop: "AAA", order: "descending" };
//全选事件
handleCheckAllChange(val: boolean) {
let _options: any = [];
this.columnsList.forEach((item: any, index: number) => {
_options.push(index);
});
this.checkList = val ? _options : [];
this.isIndeterminate = false;
}
handleCheckedCitiesChange(value: any) {
let checkedCount = value.length;
this.checkAll = checkedCount === this.columnsList.length;
this.isIndeterminate =
checkedCount > 0 && checkedCount < this.columnsList.length;
}
//读取缓存 暂时先这样
columnCache = JSON.parse(localStorage.getItem("my_column") || "[]");
//记录缓存
addCache(checkids: string) {
this.columnCache.forEach((item: any, index: number) => {
if (item.name === location.hash) {
this.columnCache.splice(index, 1);
return false;
}
});
this.columnCache.push({
name: location.hash,
value: checkids,
});
localStorage.setItem("my_column", JSON.stringify(this.columnCache));
}
//设置视图
setSlot(){
if (!this.isDefault) {
//设置列
this.$slots.diy = this._default;
}
}
//监听数据源改变
@Watch("tableData")
getTableData() {
console.log(this)
// 找出排序对象名
this.sort_default = { prop: "AAA", order: "descending" };
if ((this.$parent as any).searchKey.sort) {
Object.keys((this.$parent as any).searchKey.sort).forEach((item: any) => {
this.sort_default.prop = item;
this.sort_default.order =
(this.$parent as any).searchKey.sort[item] == 4
? "ascending"
: "descending";
});
} else if ((this.$parent as any).searchKey.default_order) {
Object.keys((this.$parent as any).searchKey.default_order).forEach(
(item: any) => {
this.sort_default.prop = item;
this.sort_default.order =
(this.$parent as any).searchKey.default_order[item] == 4
? "ascending"
: "descending";
}
);
}
if (this.isDefault) {
//重新拉取
this.columnsList = new Array();
this.columnsList = this.columnsList.concat(this.$slots.default);
}
//判定是否有缓存,有则提前设置列
this.columnCache.forEach((item: any, index: number) => {
if (item.name === location.hash) {
this.checkList = new Array();
item.value.split(",").forEach((val: string) => {
if (val) {
this.checkList.push(parseInt(val));
}
});
this.setTable(item.value);
return false;
}
});
}
//设置列
setTable(checkids = "") {
if (!checkids && this.checkList.length == 0) {
//设置默认
this.isDefault = true;
//记录缓存
this.addCache("");
//隐藏筛选器
this.cellDialog = false;
//重新渲染表格
this.isTable = false;
setTimeout(() => {
this.isTable = true;
}, 10);
return;
}
//转义字符串,用于判定方便
let _checkids = checkids ? checkids : "," + this.checkList.join(",") + ",";
//重新实例化
this._default = new Array();
//循环判定
this.columnsList.forEach((item: any, index: number) => {
if (_checkids.indexOf("," + index + ",") > -1) {
delete item.componentOptions.propsData.width;
//添加
this._default.push(item);
}
});
//设置不默认
this.isDefault = false;
//设置列
this.$slots.diy = this._default;
//重新渲染表格
this.isTable = false;
setTimeout(() => {
this.isTable = true;
}, 1);
if (!checkids) {
//记录缓存
this.addCache(_checkids);
//隐藏筛选器
this.cellDialog = false;
}
}
}
</script>
<style lang="scss">
.column_label {
width: 175px;
}
.setting{
font-size: 24px;
cursor: pointer;
float: right;
margin-top: -27px;
}
</style>