用过若依的都知道,在使用el-table 时候,实现列显隐效果是要给每个列加v-if 判断的,这种代码过于繁琐,于是翻看el-table包的代码,调试后发现内部的【插入】和【删除】两个方法可以达到我们要的效果。
项目不提供源码,核心代码都贴上了
代码动刀看似有点多,实则一个地方就一点块。el-table的源码,若依RightToolBar,本身组件,不过轮子造完都是有用的。
没有rightBar的项目可以自己对应数据模拟一个交互操作的方式来实现
上图可以看到基于若依的RightBar组件去实现列显隐,并且存到vuex的持久化中,(vuex+本地存储中),并且去掉了原先若依的RightBar组件弹窗方式。
项目是用tailwindcss 部分class类名自己去计算
RightBar的使用方法和修改内容
<right-toolbar
:showSearch.sync="showSearch"
@queryTable="getList"
:checkTableInfo.sync="checkTableInfo"
@interaction="x => (hiddenColumns = x)"
:componentName="$options.name"
/>
<template>
<div class="top-right-btn" :style="style">
<el-row>
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top" v-if="search">
<el-button size="mini" circle icon="el-icon-search" @click="$emit('update:showSearch', !showSearch)" />
</el-tooltip>
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
<el-button size="mini" circle icon="el-icon-refresh" @click="$emit('queryTable')" />
</el-tooltip>
<el-tooltip v-if="checkTableInfo.length" class="item" effect="dark" content="显隐列" placement="bottom-start">
<el-popover v-model="visible" placement="right" trigger="click">
<el-checkbox-group v-model="checkList">
<el-checkbox class="block" v-for="(item, index) in checkTableInfo" :disabled="item === 'selection' || item === '操作'" :key="index" :label="item" />
</el-checkbox-group>
<el-divider class="my-4" />
<div>
<el-button size="mini" type="primary" @click="submit">确定</el-button>
<el-button v-if="componentName" size="mini" @click="cancel">取消</el-button>
</div>
<el-button class="ml-2.5" slot="reference" size="mini" circle icon="el-icon-menu" />
</el-popover>
</el-tooltip>
</el-row>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
name: 'RightToolbar',
data() {
return {
checkList: Array.from(this.checkTableInfo),
visible: false,
}
},
props: {
showSearch: { type: Boolean, default: true },
search: { type: Boolean, default: true },
gutter: { type: Number, default: 10 },
checkTableInfo: { type: Array, default: () => [] },
componentName: { type: String, default: '' },
},
mounted() {
if (this.componentName && this.tableColumns[this.componentName]) {
this.tableColumns[this.componentName]?.length && (this.checkList = this.tableColumns[this.componentName])
this.$emit('interaction', this.checkList)
}
},
methods: {
...mapMutations('tablecolumn', ['setTableCache']),
submit() {
this.$emit('interaction', this.checkList)
this.visible = false
if (!this.componentName) return
this.setTableCache({ key: [this.componentName], value: this.checkList })
},
cancel() {
this.tableColumns[this.componentName]?.length && (this.checkList = this.tableColumns[this.componentName])
},
},
computed: {
...mapState('tablecolumn', ['tableColumns']),
style() {
const ret = {}
if (this.gutter) {
ret.marginRight = `${this.gutter / 2}px`
}
return ret
},
},
}
</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>
主页面
给table传递props 属性checkTableInfo 属性即可 一定是包括column的所有列的label
<template>
<div>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :checkTableInfo.sync="checkTableInfo" @interaction="(x) => (hiddenColumns = x)" :componentName="$options.name" />
<el-table ref="table" :data="table.data" v-loading="table.loading" :hiddenColumns="hiddenColumns" @selection-change="(ids) => (table.ids = ids)">
<el-table-column align="center" type="selection" width="55" />
<el-table-column align="center" label="类型" prop="type" />
<el-table-column align="center" label="名称" prop="name" />
<el-table-column align="center" label="描述信息" prop="desp" />
<el-table-column align="center" label="值" prop="value" />
<el-table-column align="center" label="默认值" prop="defaultValue" />
<el-table-column align="center" label="操作" class-name="small-padding fixed-width">
<template slot-scope="{ row, column: col }">
<el-button size="mini" type="text" icon="el-icon-edit" @click="edit(row)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="del(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
// import {} from ''
export default {
name: "Untitled-1",
data() {
return {
showSearch: true,
table: {
ids: [],
table: [
{
type: 'FilePath',
name: 'probeEnforcement',
desp: '文件生成路径',
value: '/home/qchen/',
defaultValue: '3',
}
],
loading: false,
},
hiddenColumns: [],
checkTableInfo: ['selection', '类型', '名称', '描述信息', '值', '默认值', '操作'],
};
},
mounted() {},
methods: {
getList() {}
edit(row) {}
del(row) {}
},
// End
};
</script>
<style lang="css" scoped></style>
将node_modules中将table的源码找到,打开里面的table.vue
将package里面的table源码导出,复制到components/ElementUI目录下即可修改代码,需要在main.js中覆盖element的el-table,最底下贴过一个链接有覆盖的路径
<script>
import { cloneDeep } from 'lodash-es'
// watch 和props 里面加入下列两个属性
export default {
props: {
hiddenColumns: {
type: Array,
default: () => [],
},
// ... 其他props
},
watch: {
hiddenColumns: {
immediate: true,
handler(value) {
const { states } = this.store;
const { columns, _columns } = states;
requestAnimationFrame(() => {
requestAnimationFrame(() => {
if (!this.cache_columns || !this.cache_columns.length) {
this.cache_columns = cloneDeep(columns);
}
if (!value.length) return;
const show = this.cache_columns.filter((x) => value.includes(x.label));
const hide = this.cache_columns.filter((x) => !value.includes(x.label) && x.type !== "selection");
if (show.length) {
const current_label = _columns.map((item) => item.label);
const control_label = show.map((item) => item.label);
control_label.forEach((item) => {
if (!current_label.includes(item)) {
const column = show.find((x) => x.label === item);
this.store.commit("insertColumn", column, column.insertColumnIndex);
}
});
}
if (hide.length) {
this.cache_columns.forEach((item) => {
hide.forEach((ite) => {
if (item.label === ite.label) {
const column = _columns.find((x) => x.label === item.label);
column && this.store.commit("removeColumn", column);
}
});
});
}
});
});
},
},
// ... 其他监听
},
// End
};
</script>
将el-table的源码找到,翻开/El-Table/store/index.js。 约30行的位置
insertColumn(states, column, index, parent) {
let array = states._columns
if (parent) {
array = parent.children
if (!array) array = parent.children = []
}
if (typeof index !== 'undefined') {
array.splice(index, 0, column)
} else {
array.push(column)
}
if (column.type === 'selection') {
states.selectable = column.selectable
states.reserveSelection = column.reserveSelection
}
if (!column.insertColumnIndex) { // 加入 index 标识,插入时用到
column.insertColumnIndex = index
}
if (this.table.$ready) {
this.updateColumns() // hack for dynamics insert column
this.scheduleLayout()
}
},
最后将重新注册的el-table 整个文件重新注册一下,这里有操作