vue3+element-plus+ts elplus table 实现表格动态列 表格列显示与隐藏的动态控制

news/2024/12/23 6:16:11/

工作接了个需求,需要实现表格的动态列,但是后端又不参与,全权交给前端,百度搜了一下,大多都是el-table-column的for循环,我觉得用起来不爽,还得改变el-table-column的书写方式,用对象保存列的相关信息,所以搞了一个这玩应

效果就是不改变书写习惯而且还能达到前端控制列的显示与隐藏

话不多讲,上代码

哦,不对,先上效果
在这里插入图片描述
在这里插入图片描述
动态图没做过,见谅吧

项目结构

简介:

  • ColumnControl为列的控制器
  • ProjectTable为二次封装的el-table表格
  • store中用于存放列的信息以及显示信息
  • Home是使用上述三个东西的页面
    在这里插入图片描述

ColumnControl组件内容

多说一句,由于我的项目使用了自动引入,所以你复制完之后可能有的方法并没有引入,如ref,computed等属于vue,useStore属于vuex,需要自行引入
具体这些个东西都是干什么的见注释吧

<script setup lang="ts">
import { Grid } from '@element-plus/icons-vue'
import { showColumn, allColumn } from '@/store/getters'
import { CheckboxValueType } from 'element-plus'const store = useStore()// #region 全选const checkAll = ref<boolean>(true)// 选中与半选的状态控制, 条件就是 当前选中的数据个数大于0 且 小于所有列的总数
const isIndeterminate = computed<boolean>(() => {return checkList.value.length > 0 && checkList.value.length < allColumn.value.length
})// 全选与否的事件控制器
const handleCheckAllChange = (boolean: CheckboxValueType) => {if (boolean) { // 全选 checkList.value = allColumn.value.map(item => item.value)}else { // 全不选checkList.value = []}
}// #endregion 全选// #region 多选框// 当前选中的个数 用了可写的computed属性
const checkList = computed<string[]>({get: () => showColumn.value, // showColumn是存在store中的属性set: (val: string[]) => {store.dispatch('setShowColumn', val)}
})// #endregion 多选框</script><template><el-popover placement="bottom" popper-class="column-popover" :width="200" trigger="click"><template #reference><el-button circle :icon="Grid"></el-button></template><el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange">全选</el-checkbox><el-divider /><el-checkbox-group class="column-checkgroup" v-model="checkList"><el-checkbox class="column-checkgroup-item" v-for="item in allColumn" :key="item.value" :label="item.value">{{ item.label}}</el-checkbox></el-checkbox-group></el-popover>
</template><style lang="scss">
.column-popover {max-height: 330px;overflow-y: auto;.el-divider--horizontal {margin: 10px 0;}
}
.column-checkgroup {&-item {display: flex;}
}
</style>

ProjectTable组件内容

<script setup lang="ts">
import { showColumn } from '@/store/getters'
import { RendererElement } from 'vue'
import { IColumn } from '@/store/modules/table'// #region ts接口interface IPage {currentPage: numberpageSize: numbertotal: number
}interface Props {data: any[]height?: string | numberpagination?: IPagehiddenCheckbox?: booleanhiddenIndex?: boolean
}interface Emits {(e: 'selection-change', value: any[]): void
}// #endregion ts接口withDefaults(defineProps<Props>(), {data: () => [], // 表格数据height: '100%', // 表格高度hiddenCheckbox: false, // 隐藏表格多选框?hiddenIndex: false, // 隐藏表格序号?pagination: () => ({ // 翻页,看项目需求,如果翻到第二页需要从11开始,那么就需要这个currentPage: 1,pageSize: 10,total: 0})
})const emits = defineEmits<Emits>()const store = useStore()onMounted(() => {initSlotList() // 关键, 初始化插槽
})// #region 插槽const slots = useSlots()const slotList = ref<RendererElement[]>([])const initSlotList = () => {if (slots.default) { // el-table-column 使用时不传name 所以属于默认插槽slotList.value = slots.default() || [] // 语法initDynamicColumn() // 初始化动态列}
}// 初始化动态列
const initDynamicColumn = () => {const checkboxList: IColumn[] = [] // 所有列slotList.value.map(item => {const props = item.props// 存在prop属性 label为表头名称if (props && typeof props === 'object' && props.prop) {checkboxList.push({ value: props.prop, label: props.label })}})store.dispatch('setAllColumn', checkboxList)
}// #endregion 插槽// 表格多选事件
const selectionChange = (list: any[]) => {emits('selection-change', list)
}</script><template><el-table :data="data" border stripe :height="height" @selection-change="selectionChange"header-cell-class-name="header-cell"><el-table-column v-if="!hiddenCheckbox" type="selection" align="center" width="55" /><el-table-column v-if="!hiddenIndex" type="index" align="center" label="#" width="60"><template #default="{ $index }"><div>{{ $index + (pagination.currentPage - 1) * pagination.pageSize + 1 }}</div></template></el-table-column><!-- 这个template 属于核心代码了 --><template v-for="(item, index) in slotList" :key="index"><component v-if="showColumn.includes(item.props.prop)" :is="item"></component></template></el-table>
</template><style lang="scss" scoped>
</style>

store仓库

别问为什么用vuex 不用pinia 问就是不会

index.ts文件

import table from './modules/table'const store = createStore({modules: {table}
})export default store

getters.ts文件


import { IColumn } from './modules/table'
import store from './index'// vue3 组合api 没法使用mapGetters   弄了个这玩应凑合用export const allColumn = computed<IColumn[]>(() => {return store.getters.allColumn
})export const showColumn = computed<string[]>(() => {return store.getters.showColumn
})

table.ts文件


import { Module } from 'vuex' // #region ts接口export interface IColumn {value: stringlabel: string
}interface IState {allColumn: IColumn[]showColumn: string[]
}// #endregion ts接口// Module<S, R> S表示咱们这个页面(table.ts)中的state类型
// R: 由于咱们是模块, 在外面的store使用 store.modules = {table} 挂载的咱们
// 而外面的store也会有 state 属性, 这个R就是外面state属性的类型
// 由于我的store/index.ts没写state,所以这里给个any
const table: Module<IState, any> = {state() {return {allColumn: [], // 表格全部的列 格式 IColumnshowColumn: [] // 当前展示的列 }},getters: {allColumn(state) {return state.allColumn},showColumn(state) {return state.showColumn}},mutations: {SET_ALL_COLUMN(state, data) {state.allColumn = data},SET_SHOW_COLUMN(state, data) {state.showColumn = data}},// 使用时 用actions进行数据更改, 尽量不要使用mutations, 没原因, 建议而已actions: {setAllColumn({ commit }, data: IColumn[]) {commit('SET_ALL_COLUMN', data)// 设置全部列时 默认展示所有的列const showColumn = data.map(item => item.value)commit('SET_SHOW_COLUMN', showColumn)},setShowColumn({ commit }, data: string[]) {commit('SET_SHOW_COLUMN', data)}}
}export default table

Home页面

<script setup lang="ts">// #region ts接口interface ITableRow {name: string,age: number,random: number
}interface IPage {currentPage: numberpageSize: numbertotal: number
}// #endregion ts接口onMounted(() => {getList()
})// #region 表格// 分页数据, 本例由于动态表格封装所以弄了一个
const pagination = ref<IPage>({currentPage: 1,pageSize: 10,total: 0
})const tableData = ref<ITableRow[]>([])// 获取列表
const getList = () => {const list: ITableRow[] = []for (let i = 0; i < 5; i++) {list.push({name: '姓名' + Math.floor(Math.random() * 10),age: Math.floor(Math.random() * 100),random: Math.random()})}tableData.value = list
}// #endregion 表格</script><template><div class="home"><div class="home-buttons"><div class="home-buttons-opra"><el-button type="primary">没用,占位</el-button></div><div class="home-buttons-tools"><ColumnControl /></div></div><div class="home-list"><!-- 如果要隐藏多选或者序号或者你扩展了什么 <ProjectTable hiddenIndex> 你懂得! --><ProjectTable :pagination="pagination" :data="tableData" ><!-- 使用时就正常使用,不需要写for循环 --><el-table-column prop="name" label="姓名" /><el-table-column prop="age" label="年龄" /><el-table-column prop="random" label="随机数" /></ProjectTable></div></div>
</template><style lang="scss" scoped>
.home {width: 700px;display: flex;flex-direction: column;&-buttons {margin-bottom: 12px;display: flex;justify-content: space-between;align-items: center;}
}
</style>

总结

这玩应在使用时除了引用ColumnControl和ProjectTable两个组件以外,与你普通书写el-table是一样的,你也不用重新弄个数组保存所有的列,实现这东西的时候是真的难受,用的时候是爽的不要不要的
注意!!!!!!
我写的这个玩应只是一个最最基本的,没有缓存功能,也没跟用户挂钩,甚至你都不需要关浏览器或者重新登陆,你只要切换一个页面再切回来,这时你刚刚隐藏的列就又会被显示出来,当然要解决这些问题也是完全可以的,不过现在是周五下午五点了,我要下班了,伟大的扩展任务就交给你们了!


http://www.ppmy.cn/news/91032.html

相关文章

【Linux】普通用户无法使用sudo指令的方法

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;Linux &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【Linux】…

JavaEE——自主实现计时器

文章目录 一、认识定时器二、自主实现定时器1.明确定时器的内核原理2.定时器框架搭建3.优先级队列中的比较问题4.“忙等”问题5. 代码中随机调度的问题 三、整体代码罗列 一、认识定时器 什么是定时器 定时器是我们在日常的软件开发中很重要的一个组件。类似于闹钟&#xff0c…

Git常用命令reset和revert

Git常用命令reset和revert 1、reset 用于回退版本&#xff0c;可以指定退回某一次提交的版本。 checkout 可以撤销工作区的文件&#xff0c;reset 可以撤销工作区/暂存区的文件。 reset 和 checkout 可以作用于 commit 或者文件&#xff0c;revert 只能作用于 commit。 命…

成功上岸奇安信!这份零基础入门网络安全的学习路线你一定要看,学长带你网络安全从入门到就业!

作为一个实用型技术博主&#xff0c;​由于我之前写了不少网络安全技术相关的文章&#xff0c;不少读者朋友知道我是从事网络安全相关的工作&#xff0c;于是经常有人在后台问我&#xff1a; 现在转行学网络安全是一个正确的选择吗&#xff1f;我刚入门网络安全&#xff0c;该…

基于OpenCV和PyQt5的跳远成果展示程序

基于OpenCV和PyQt5的跳远成果展示程序 近年来&#xff0c;体育运动越来越受到人们的关注&#xff0c;其中跳远是一项备受瞩目的运动项目。为了更好地展示运动员的跳远成果&#xff0c;本文将介绍一种基于OpenCV和PyQt5的跳远成果展示程序实现方法。 本文的跳远成果展示程序主…

牛顿-莱布尼茨公式练习习题

前置知识&#xff1a;牛顿-莱布尼茨公式 习题1 已知 F ( x ) ∫ 0 x 1 − t d t ( x ≤ 1 ) F(x)\int_0^x\sqrt{1-t}dt(x\leq 1) F(x)∫0x​1−t ​dt(x≤1)&#xff0c;求 F ′ ( x ) F(x) F′(x) 解&#xff1a; \qquad 当 x 0 ∈ [ 0 , 1 ] x_0\in[0,1] x0​∈[0,1]时&…

vcruntime140.dll丢失的解决方法?教你如何修复好dll文件

Vcruntime140.dll文件是Windows操作系统中非常重要的一个动态链接库文件&#xff0c;用于支持使用Microsoft Visual C编译器创建的应用程序的运行。当Windows系统中的vcruntime140.dll文件丢失时&#xff0c;可能会导致某些应用程序无法正常启动。在尝试启动应用程序时&#xf…

【2023年电工杯竞赛】B题 人工智能对大学生学习影响的评价 数学建模方案和python代码

1 题目 B题 人工智能对大学生学习影响的评价 人工智能简称AI&#xff0c;最初由麦卡锡、明斯基等科学家于1956年在美国达特茅斯学院开会研讨时提出。 2016年&#xff0c;人工智能AlphaGo 4:1战胜韩国围棋高手李世石&#xff0c;期后波士顿动力公司的人形机器人Atlas也展示了…