您现在的位置是:首页 >其他 >vue3+element-plus+ts elplus table 实现表格动态列 表格列显示与隐藏的动态控制 支持传递插槽与多级表头网站首页其他
vue3+element-plus+ts elplus table 实现表格动态列 表格列显示与隐藏的动态控制 支持传递插槽与多级表头
简介vue3+element-plus+ts elplus table 实现表格动态列 表格列显示与隐藏的动态控制 支持传递插槽与多级表头
如题
先上效果
部分代码展示
Home页面
使用时除了名字不同其他没啥不同,但是我这个封装的函数或者属性较少,如果需要请自行增加
<script setup lang="ts">
import { IPage } from '@/mixins/pagination'
import { TableKey } from '@/types/enum'
import { useRouter } from 'vue-router'
const router = useRouter()
// #region ts接口
interface ITableRow {
name: string,
age: number,
random: number
}
// #endregion ts接口
onMounted(() => {
getList()
})
// #region 跳转
const toTable = () => {
router.push({
name: 'Table'
})
}
// #endregion 跳转
// #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">
<h1>home页面</h1>
<div class="home-buttons">
<div class="home-buttons-opra">
<el-button type="primary" @click="toTable" >跳转到表格页</el-button>
</div>
<div class="home-buttons-tools">
<ColumnControl :column-key="TableKey.HOME" />
</div>
</div>
<div class="home-list">
<ProjectTable :pagination="pagination" :data="tableData" :column-key="TableKey.HOME">
<ProjectColumn label="人">
<ProjectColumn prop="name" label="姓名" />
<ProjectColumn prop="age" label="年龄" >
<template #default="{ row }">
<div>
{{ row.age }}
</div>
</template>
</ProjectColumn>
</ProjectColumn>
<ProjectColumn prop="random" label="随机数">
<template #default="{ row }">
<div>
{{ row.random }}
</div>
</template>
</ProjectColumn>
</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>
二次封装的表格
<script setup lang="ts">
import ProjectColumn from '@/components/ProjectColumn/index.vue'
import { IPage } from '@/mixins/pagination'
import { TableKey } from '@/types/enum'
import { IColumn, ISetColumn, ISetShowColumn } from '@/store/modules/table'
import { useColumn } from '@/use/useColumn'
import { RendererElement } from 'vue'
const store = useStore()
// #region ts接口
interface Props {
data: any[]
height?: string | number
pagination?: IPage
hiddenCheckbox?: boolean
hiddenIndex?: boolean
columnKey: TableKey
}
interface Emits {
(e: 'selection-change', value: any[]): void
}
// #endregion ts接口
// #region 组件传值
const props = withDefaults(defineProps<Props>(), {
height: '100%',
pagination: () => ({
currentPage: 1,
pageSize: 10,
total: 0
}),
hiddenCheckbox: false,
hiddenIndex: false
})
const emits = defineEmits<Emits>()
// #endregion 组件传值
onMounted(() => {
initSoltList()
})
// #region 表格
// 多选切换
const selectionChange = (list: any[]) => {
emits('selection-change', list)
}
// #endregion 表格
// #region 插槽
const slots = useSlots()
// 当前显示的插槽
const { showColumn } = useColumn(props.columnKey)
// 渲染时的插槽列表
const slotList = ref<RendererElement[]>([])
// 递归时保存全部的动态列
const tempAllColumn = ref<IColumn[]>([])
// 递归时顺便设置展示列
const tempShowColumn = ref<string[]>([])
// 初始化
const initSoltList = () => {
if (slots.default) {
slotList.value = slots.default() || []
setUnique(slotList.value)
// 如果存在展示列, 则不需要重新赋值了
if (showColumn.value.length > 0) {
return
}
const columnData: ISetColumn = {
key: props.columnKey,
value: tempAllColumn.value
}
store.dispatch('setAllColumn', columnData)
const showColumnData: ISetShowColumn = {
key: props.columnKey,
value: tempShowColumn.value
}
store.dispatch('setShowColumn', showColumnData)
}
}
// 设置唯一键, 利用js浅拷贝 此函数执行完成会改变 tempAllColumn 并 设置展示列 tempShowColumn
const setUnique = (list: RendererElement[], prefix?: string, column?: IColumn) => {
list.map(item => {
// 是column组件 且 具有label属性
// ProjectColumn 是 组件ProjectColumn
if (
(item.type && item.type === ProjectColumn)
&& (item.props && item.props.label)
) {
let tempColumn: IColumn = {
value: '',
label: ''
}
// 如果存在前缀 表示是子级
if (prefix && column) {
tempColumn = {
value: `${prefix}-${item.props.label}`,
label: item.props.label
}
if (!column.children) {
column.children = []
}
column.children.push(tempColumn)
} else { // 不存在前缀 表示不是子级
tempColumn = {
value: item.props.label,
label: item.props.label
}
tempAllColumn.value.push(tempColumn)
}
tempShowColumn.value.push(tempColumn.value) // 设置展示列
if (item.children && item.children.default) { // 存在子级
const tempChildrenList = item.children.default({ row: {}, column: {}, $index: -1 })
// console.log('tempChildrenList', tempChildrenList)
setUnique(tempChildrenList, tempColumn.value, tempColumn)
}
}
})
}
// #endregion 插槽
</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 v-for="(item, index) in slotList" :key="index">
<component v-if="showColumn.includes(item.props?.label)" :uni-key="item.props?.label" :column-key="columnKey" :is="item"></component>
</template>
</el-table>
</template>
<style lang="scss" scoped></style>
其余页面不予展示了,请下载代码后自行查看
由于代码和页面较多,所以不在此文档进行展示,以下是项目地址,具体功能请下载会后自行体验
注意: 由于代码使用了自动导入,刚下载完代码如果不启动的话,会有报错,是因为没有引入,当项目启动后就会运行自动导入,这时就不会报错了
代码内具有部分注释,如果不清楚或者有BUG可在本章进行评论,谢谢
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。