Table 表格
gi-table 组件是基于 Element Plus 的 el-table 和 el-pagination 组件封装的高级表格组件,提供了更便捷的配置方式和增强的功能,包括动态列配置、自定义渲染、嵌套列支持、分页集成等
基础用法
- 1
查看代码
vue
<template>
<gi-page-layout bordered style="height: 500px">
<template #tool>
<el-row justify="space-between" class="gi-tool gi-w-full">
<el-space warp>
<gi-button type="add"></gi-button>
<gi-button type="delete"></gi-button>
</el-space>
<el-space warp>
<el-input v-model="queryParams.keyword" placeholder="搜索姓名或地址" clearable style="width: 200px" />
<ElButton type="primary" @click="search">搜索</ElButton>
</el-space>
</el-row>
</template>
<gi-table v-loading="loading" :columns="columns" :data="tableData" :pagination="pagination">
<template #action="scope">
<el-space>
<ElButton type="primary" size="small" @click="onEdit(scope.row)">编辑</ElButton>
<ElButton type="danger" size="small">删除</ElButton>
</el-space>
</template>
</gi-table>
</gi-page-layout>
</template>
<script lang="ts" setup>
import type { TableColumnItem } from 'gi-component'
import { getUserList } from '@docs/_apis/mockTable'
import { useTable } from '@docs/_hooks'
import { ElButton, ElMessage, ElTag } from 'element-plus'
import { h, reactive } from 'vue'
const columns: TableColumnItem[] = [
{ type: 'selection', width: 55, align: 'center', fixed: 'left' },
{ type: 'index', label: '序号', width: 60, align: 'center' },
{
prop: 'name',
label: '姓名',
width: 100,
align: 'center',
showOverflowTooltip: true
},
{ prop: 'age', label: '年龄', width: 60, align: 'center' },
{
prop: 'sex',
label: '性别',
width: 80,
align: 'center',
render: ({ row }) => {
return h(
ElTag,
{ type: row.sex === '男' ? 'primary' : 'danger', size: 'small' },
{ default: () => row.sex }
)
}
},
{
prop: 'address',
label: '地址'
},
{ prop: 'remark', label: '描述', width: 150, showOverflowTooltip: true },
{
prop: 'action',
label: '操作',
width: 140,
align: 'center',
slotName: 'action',
fixed: 'right'
}
]
const queryParams = reactive({
keyword: ''
})
const { tableData, getTableData, pagination, search, refresh, loading } = useTable((p) => getUserList({ ...p, ...queryParams }), {
onSuccess: () => {
// ElMessage.success(`页码${pagination.currentPage}, 页数${pagination.pageSize}条--数据成功加载`);
}
})
// 编辑操作
function onEdit(scope: any) {
ElMessage.success(`编辑 ${scope.row.name}`)
}
</script>
<style lang="scss" scoped></style>表头搜索
本示例只提供技巧参考,实际项目请根据自身需求进行封装useTableHeaderSearch函数hooks
- 1
{}查看代码
vue
<template>
<gi-page-layout bordered style="height: 500px">
<template #tool>
<el-row justify="space-between" class="gi-tool gi-w-full">
<el-space warp>
<gi-button type="add"></gi-button>
<gi-button type="delete"></gi-button>
</el-space>
<el-space warp>
<el-input v-model="queryParams.keyword" placeholder="搜索姓名或地址" clearable style="width: 200px" />
<ElButton type="primary" @click="search">搜索</ElButton>
</el-space>
</el-row>
</template>
<gi-table v-loading="loading" :columns="columns" :data="tableData" :pagination="pagination" border>
<template #action="scope">
<el-space>
<ElButton type="primary" size="small" @click="onEdit(scope)">编辑</ElButton>
<ElButton type="danger" size="small">删除</ElButton>
</el-space>
</template>
</gi-table>
<pre class="doc-pre">{{ headerParams }}</pre>
</gi-page-layout>
</template>
<script lang="ts" setup>
import type { UserItem } from '@docs/_apis/mockTable'
import type { TableColumnItem } from 'gi-component'
import { getUserList } from '@docs/_apis/mockTable'
import { useTable } from '@docs/_hooks'
import { ElButton, ElMessage, ElTag } from 'element-plus'
import { h, reactive } from 'vue'
import { useTableHeaderSearch } from './components/useTableHeaderSearch'
const queryParams = reactive({
keyword: ''
})
const { tableData, getTableData, pagination, search, refresh, loading } = useTable((p) => getUserList({ ...p, ...queryParams }), {
onSuccess: () => {
// ElMessage.success(`页码${pagination.currentPage}, 页数${pagination.pageSize}条--数据成功加载`);
}
})
const { headerParams, createTableHeader } = useTableHeaderSearch({ search: () => search() })
const columns: TableColumnItem<UserItem>[] = [
{ type: 'selection', width: 55, align: 'center', fixed: 'left' },
{ type: 'index', label: '序号', width: 60, align: 'center' },
{
prop: 'name',
label: '姓名',
width: 100,
align: 'center',
showOverflowTooltip: true,
renderHeader: () => createTableHeader({ type: 'input', label: '姓名', field: 'name' })
},
{ prop: 'age', label: '年龄', width: 60, align: 'center' },
{
prop: 'sex',
label: '性别',
width: 80,
align: 'center',
render: ({ row }) => {
return h(
ElTag,
{ type: row.sex === '男' ? 'primary' : 'danger', size: 'small' },
{ default: () => row.sex }
)
},
renderHeader: () => createTableHeader({ type: 'checkbox-group', label: '性别', field: 'sex' })
},
{
prop: 'address',
label: '地址',
children: [
{ prop: 'city', label: '城市', width: 100 },
{ prop: 'district', label: '区县', width: 100 }
]
},
{ prop: 'remark', label: '描述', width: 150, showOverflowTooltip: true },
{
prop: 'action',
label: '操作',
width: 140,
align: 'center',
slotName: 'action',
fixed: 'right'
}
]
// 编辑操作
function onEdit(scope: any) {
ElMessage.success(`编辑 ${scope.row.name}`)
}
</script>
<style lang="scss" scoped></style>useTableHeaderSearch.ts
ts
import { h, reactive } from 'vue'
import HeaderCheckboxGroup from './HeaderCheckboxGroup.vue'
import HeaderInput from './HeaderInput.vue'
export function useTableHeaderSearch(options: { search: () => void }) {
const headerParams = reactive({} as Record<string, any>)
function createTableHeader(params: { type: 'input' | 'checkbox-group', label: string, field: string }) {
if (params.type === 'input') {
return h(HeaderInput, { headerParams, label: params.label, field: params.field, onConfirm: () => options.search() })
}
if (params.type === 'checkbox-group') {
return h(HeaderCheckboxGroup, { headerParams, label: params.label, field: params.field, onConfirm: () => options.search() })
}
return h('div', {}, params.label)
}
return {
headerParams,
createTableHeader
}
}HeaderInput.vue
vue
<template>
<el-popover v-model:visible="visible" placement="bottom" :width="200">
<template #reference>
<HeaderLabel :label="props.label" :actived="!!props.headerParams[props.field]" @click="visible = true">
</HeaderLabel>
</template>
<el-input v-model="props.headerParams[props.field]" :placeholder="`输入${props.label}查询`" clearable
size="small"></el-input>
<el-row justify="end" style="margin-top: 10px">
<el-space>
<el-button size="small" @click="visible = false">取消</el-button>
<el-button type="primary" size="small" @click="onConfirm">确定</el-button>
</el-space>
</el-row>
</el-popover>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import HeaderLabel from './HeaderLabel.vue'
interface Props {
label: string
field: string
headerParams: Record<string, any>
}
const props = withDefaults(defineProps<Props>(), {})
const emit = defineEmits<{
(e: 'confirm'): void
}>()
const visible = ref(false)
function onConfirm() {
emit('confirm')
visible.value = false
}
</script>HeaderCheckboxGroup.vue
vue
<template>
<el-popover :visible="visible" placement="bottom" :width="200" :popper-style="{ width: '140px', minWidth: '0px' }">
<template #reference>
<HeaderLabel :label="props.label" :actived="!!props.headerParams[props.field]?.length" @click="visible = true">
</HeaderLabel>
</template>
<el-checkbox-group v-model="props.headerParams[props.field]" :options="options" />
<el-row justify="end" style="margin-top: 10px">
<el-space>
<el-button size="small" @click="visible = false">取消</el-button>
<el-button type="primary" size="small" @click="onConfirm">确定</el-button>
</el-space>
</el-row>
</el-popover>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import HeaderLabel from './HeaderLabel.vue'
interface Props {
label: string
field: string
headerParams?: Record<string, any>
}
const props = withDefaults(defineProps<Props>(), {
headerParams: () => ({})
})
const emit = defineEmits<{
(e: 'confirm'): void
}>()
const visible = ref(false)
const options = [
{ label: '男', value: '1' },
{ label: '女', value: '2' }
]
function onConfirm() {
emit('confirm')
visible.value = false
}
</script>
<style lang="scss" scoped>
:deep(.el-checkbox) {
display: flex;
margin-right: 0;
}
</style>API 使用说明
组件属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| columns | TableColumnItem[] | [] | 表格列配置数组 |
| data | any[] | - | 表格数据 |
| pagination | Partial<PaginationProps> | boolean | {} | 分页配置 |
| 其他属性 | - | - | 支持 Element Plus Table 组件的所有属性 |
TableColumnItem 接口
TableColumnItem 接口继承自 Element Plus 的 TableColumnInstance['$props'],并扩展了以下属性:
| 属性名 | 类型 | 说明 |
|---|---|---|
| slotName | string | 用于自定义列内容的插槽名称 |
| children | TableColumnItem[] | 子列配置,用于创建嵌套表头 |
| render | (scope: TableColumnCtx<any>) => VNode | VNode[] | string | 自定义渲染函数,用于动态生成单元格内容 |
| 其他属性 | - | 支持 Element Plus TableColumn 的所有属性 |
Pagination 配置
pagination 属性支持 Element Plus Pagination 组件的所有配置项,常用配置如下:
事件
支持 Element Plus Table 组件的所有事件。
插槽
除了通过 slotName 属性定义的自定义列插槽外,还支持 Element Plus Table 组件的所有作用域插槽。
