ProTable
示例
基本使用
props为$index自动生成索引
<template>
<div>
<SuperProTable
ref="proTable"
:columns="columns"
:data="data"
></SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
])
const columns = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名', width: 200 },
{ prop: 'address', label: '居住地址' },
])
</script>
单元格数据状态(tag)
传入tag函数实现不同数据状态样式
<template>
<div>
<SuperProTable
ref="proTable"
:columns="columns"
:data="data"
></SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
date: Date.now(),
name: '张三',
address: '北京',
tag: 0
},
{
date: Date.now(),
name: '张三',
address: '北京',
tag: 1
},
{
date: Date.now(),
name: '张三',
address: '北京',
tag: 2
},
{
date: Date.now(),
name: '张三',
address: '北京',
tag: 3
},
])
const columns = reactive<ColumnProps<any>[]>([
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名', width: 200 },
{ prop: 'address', label: '居住地址' },
{
prop: 'tag',
label: '标签',
tag: ({ row }) => {
switch (row.tag) {
case 0:
return { type: 'success' }
case 1:
return { type: 'info' }
case 2:
return { type: 'warning' }
case 3:
return { type: 'danger' }
default:
break
}
},
},
])
</script>
单元格对齐方式
表格默认为居中对齐,如果需要修改对齐方式,请设置align属性, 每列对齐方式可以单独设置
<template>
<div>
<SuperProTable
ref="proTable"
:columns="columns"
:data="data"
align="left"
></SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
])
const columns = reactive<ColumnProps<any>[]>([
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名', width: 200, align: 'center' },
{ prop: 'address', label: '居住地址' },
])
</script>
固定表头
设置 height 属性,即可实现固定表头的表格
<template>
<div>
<SuperProTable
ref="proTable"
:columns="columns"
:data="data"
height="300px"
></SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([])
Array.from({ length: 50 }).forEach((_, index) => {
data.push({
date: Date.now(),
name: '张三' + index,
address: '北京' + index,
},)
})
const columns = reactive<ColumnProps<any>[]>([
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名', width: 200 },
{ prop: 'address', label: '居住地址' },
])
</script>
多级表头
设置 _children 属性,即可实现多级表头表格
<template>
<div>
<SuperProTable ref="proTable" :columns="columns" :data="data"></SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
date: Date.now(),
name: '张三',
province: "湖北省",
city: "武汉市",
area: "汉阳区",
},
{
date: Date.now(),
name: '张三',
province: "湖北省",
city: "武汉市",
area: "汉阳区",
},
{
date: Date.now(),
name: '张三',
province: "湖北省",
city: "武汉市",
area: "汉阳区",
},
])
const columns = reactive<ColumnProps<any>[]>([
{ prop: 'date', label: '日期' },
{
prop: 'base',
label: '配送信息',
_children: [
{ prop: 'name', label: '姓名' },
{
prop: 'address',
label: '地址',
_children: [
{ prop: 'province', label: '省份' },
{ prop: 'city', label: '市区' },
{ prop: 'area', label: '具体地址' },
],
},
],
},
])
</script>
表格多选
警告: rowKey必须设置
<template>
<div>
<div>选中的数据: {{ selectedList }}</div>
<div>选中的数据id: {{ selectedListIds }}</div>
<el-checkbox v-model="ifContinuousMultiple">是否开启连续勾选列表数据({{ ifContinuousMultiple }})</el-checkbox>
<el-button @click="() => treeProTableRef.clearSelection()">清空数据</el-button>
<SuperProTable
ref="proTable"
rowKey="id"
:columns="columns"
:data="data"
:ifContinuousMultiple="ifContinuousMultiple"
></SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, useTemplateRef, computed } from 'vue'
import type { ColumnProps } from '@super-ui-plus/types'
const ifContinuousMultiple = ref(true)
const data = reactive<any[]>([])
Array.from({ length: 50 }).forEach((_, index) => {
data.push({
id: index,
date: Date.now(),
name: '张三' + index,
address: '北京' + index,
},)
})
const columns = reactive<ColumnProps<any>[]>([
{ type: 'selection', width: 80 },
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名', width: 200 },
{ prop: 'address', label: '居住地址' },
])
const treeProTableRef: any = useTemplateRef('proTable')
const selectedList: any = computed(() => treeProTableRef.value?.selectedList)
const selectedListIds: any = computed(() => treeProTableRef.value?.selectedListIds)
</script>
多选树
<template>
<div>
<div>选中的数据: {{ selectedList }}</div>
<div>选中的数据id: {{ selectedListIds }}</div>
<el-button @click="() => treeProTableRef.clearSelection()">清空数据</el-button>
<SuperProTable ref="treeProTable" :columns="treeColumns" :data="treeData"></SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive, useTemplateRef, computed } from 'vue'
import type { ColumnProps } from '@super-ui-plus/types'
// 生成树形结构数据
// 定义树节点类型
interface TreeNode {
id: string
date: number
name: string
address: string
children?: TreeNode[]
}
const generateTreeData = (level = 0, count = 10, parentId: string | null = null) => {
const data: TreeNode[] = []
for (let i = 0; i < count; i++) {
const id = parentId ? `${parentId}-${i}` : `${i}`
const item: TreeNode = {
id,
date: Date.now(),
name: `张三${level}-${i}`,
address: `北京${level}-${i}`,
}
// 添加子节点(最多3层)
if (level < 2 && Math.random() > 0.3) {
item.children = generateTreeData(level + 1, Math.floor(Math.random() * 3) + 1, id)
}
data.push(item)
}
return data
}
const treeData = reactive<any[]>(generateTreeData())
const treeColumns = reactive<ColumnProps<any>[]>([
{ type: 'selection', width: 80 },
{ type: 'index', width: 80 },
{ prop: 'date', label: '日期' },
{ prop: 'name', label: '姓名' },
{ prop: 'address', label: '地址' },
])
const treeProTableRef: any = useTemplateRef('treeProTable')
const selectedList: any = computed(() => treeProTableRef.value?.selectedList)
const selectedListIds: any = computed(() => treeProTableRef.value?.selectedListIds)
</script>
展开行/单选列/拖拽排序
<template>
<div>
<SuperProTable ref="proTable" :columns="columns" :data="data" rowKey="id" @drag-sort="sortTable">
<template #expand="scope">
{{ scope.row }}
</template>
</SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive, useTemplateRef, watch } from 'vue'
import { ElMessage } from 'element-plus'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
id: 1,
date: Date.now(),
name: '张三',
address: '北京',
},
{
id: 2,
date: Date.now(),
name: '张三',
address: '北京',
},
{
id: 3,
date: Date.now(),
name: '张三',
address: '北京',
},
])
const columns = reactive<ColumnProps<any>[]>([
{ type: "sort", label: "Sort", width: 60 },
{ type: 'radio', label: '单选', width: 60 },
{ type: 'expand', label: 'Expand', width: 60 },
{ prop: 'date', label: '日期' },
{ prop: 'name', label: '姓名' },
{ prop: 'address', label: '居住地址' },
])
const proTableRef = useTemplateRef('proTable')
watch(
() => proTableRef.value?.radio,
() =>
proTableRef.value?.radio &&
ElMessage.success(`选中 id 为【${proTableRef.value?.radio}】的数据`),
)
// 表格拖拽排序
const sortTable = ({ newIndex, oldIndex }: { newIndex?: number; oldIndex?: number }) => {
console.log(newIndex, oldIndex);
console.log(proTableRef.value?.tableData);
ElMessage.success("修改列表排序成功");
};
</script>
自定义渲染表头(slot/tsx)
通过 插槽 和 headerRender 属性,可以自定义表头
<template>
<div>
<SuperProTable ref="proTable" :columns="columns" :data="data">
<template #usernameHeader="scope">
<el-button type="primary" @click="ElMessage.success('我是通过作用域插槽渲染的表头')">
{{ scope.column.label }}
</el-button>
</template>
</SuperProTable>
</div>
</template>
<script lang="tsx" setup>
import { reactive } from 'vue'
import { ElButton, ElMessage } from 'element-plus'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
date: Date.now(),
name: '张三',
address: '北京',
username: '无名的人'
},
{
date: Date.now(),
name: '张三',
address: '北京',
username: '无名的人'
},
{
date: Date.now(),
name: '张三',
address: '北京',
username: '无名的人'
},
])
// 自定义渲染表头(使用tsx语法)
const headerRender = (scope: any) => {
return (
<ElButton type="primary" onClick={() => ElMessage.success('我是通过 tsx 语法渲染的表头')}>
{scope.column.label}
</ElButton>
)
}
const columns = reactive<ColumnProps<any>[]>([
{ prop: 'date', label: '日期', headerRender, width: 200 },
{ prop: 'name', label: '姓名', width: 200 },
{ prop: 'address', label: '居住地址' },
{ prop: 'username', label: '用户名' },
])
</script>
自定义渲染内容(slot/tsx)
通过 插槽 和 reder 属性,可以自定义单元格内容
<template>
<div>
<SuperProTable ref="proTable" :columns="columns" :data="data">
<template #name="scope">
<el-button type="primary" link @click="ElMessage.success('我是通过作用域插槽渲染的内容')">
{{ scope.row.name }}
</el-button>
</template>
</SuperProTable>
</div>
</template>
<script lang="tsx" setup>
import { reactive } from 'vue'
import { ElButton, ElMessage } from 'element-plus'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
])
const columns = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名', width: 200 },
{
prop: 'address',
label: '居住地址',
render: scope => {
return (
<ElButton
type="primary"
link
onClick={() => ElMessage.success('我是通过 tsx 语法渲染的内容')}
>
{scope.row.address}
</ElButton>
)
},
},
])
</script>
表尾合计行
show-summary属性显示表尾合计行
sumText: 自定义合计行文本
sumNaNText: 当数据为非数字时,该字段用于代替合计行显示的值
sumDataPrefix: 自定义合计数据前缀
sumFilter: 自定义合计内容
<template>
<div>
<SuperProTable
ref="proTable"
:columns="columns"
:data="data"
:show-summary="true"
sumText="自定义合计行文本"
sumNaNText="自定义非数字数据"
></SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
name: '张三',
chineseZodiac: '🐎',
n1: '1',
n2: '2',
n3: '3',
n4: '4',
n5: '5',
},
{
name: '张三',
chineseZodiac: '🐎',
n1: '1',
n2: '2',
n3: '3',
n4: '4',
n5: '5',
},
{
name: '张三',
chineseZodiac: '🐎',
n1: '1',
n2: '2',
n3: '3',
n4: '4',
n5: '5',
},
])
const columns = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'name', label: '姓名' },
{ prop: 'chineseZodiac', label: '生肖', sumFilter: () => '🐎' },
{ prop: 'n1', label: '数值1', sumDataPrefix: '$' },
{ prop: 'n2', label: '数值2', sumDataPrefix: '¥' },
{ prop: 'n3', label: '数值3', sumFilter: (val) => '$' + val },
{ prop: 'n4', label: '数值4', sumDataPrefix: '¥' },
{ prop: 'n5', label: '数值5' },
])
</script>
分页自动滚动到首行
通过 autoScroll 控制分页自动滚动到首行
<template>
<div>
<SuperProTable
ref="proTable"
:columns="columns"
:data="data"
:autoScroll="true"
height="300px"
></SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([])
Array.from({ length: 50 }).forEach(() => {
data.push({
date: Date.now(),
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
})
})
const columns = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名', width: 200 },
{ prop: 'address', label: '居住地址' },
])
</script>
数据格式化
通过 format 实现数据格式化
目前只内置了日期格式化,通过传入 year,month,date显示效果
<template>
<div>
<SuperProTable
ref="proTable"
:columns="columns"
:data="data"
></SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
date: Date.now(),
name: '张三',
address: '北京',
tag: 0,
},
{
date: Date.now(),
name: '张三',
address: '北京',
tag: 0,
},
{
date: Date.now(),
name: '张三',
address: '北京',
tag: 0,
},
])
const columns = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', format: 'year', width: 100 },
{ prop: 'name', label: '姓名', width: 100 },
{ prop: 'address', label: '居住地址', format: value => '我家住在:' + value },
{
prop: 'tag',
label: '标签',
tag: ({ row }) => {
switch (row.tag) {
case 0:
return { type: 'success' }
case 1:
return { type: 'info' }
case 2:
return { type: 'warning' }
case 3:
return { type: 'danger' }
default:
break
}
},
width: 100
},
])
</script>
行和列合并
通过 span-method 实现
<template>
<div>
<SuperProTable
ref="proTable"
:columns="columns"
:data="data"
:span-method="objectSpanMethod"
></SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import type { ColumnProps } from '@super-ui-plus/types'
import type { TableColumnCtx } from "element-plus/es/components/table/src/table-column/defaults";
const data = reactive<any[]>([])
Array.from({ length: 50 }).forEach(() => {
data.push({
date: Date.now(),
name: '王小虎',
address: '上海市普陀区',
address2: '金沙江路 1518 弄'
})
})
const columns = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名', width: 200 },
{ prop: 'address', label: '居住地址' },
{ prop: 'address2', label: '具体地址' },
])
// 列合并
interface SpanMethodProps {
row: any;
column: TableColumnCtx<any>;
rowIndex: number;
columnIndex: number;
}
const objectSpanMethod = ({ rowIndex, columnIndex }: SpanMethodProps) => {
// 行合并
if (rowIndex % 2 === 0) {
if (columnIndex === 3) { // 合并第 3 列和第 4 列
return [1, 2]
} else if (columnIndex === 4) { // 被合并的列需要返回0
return [0, 0]
}
}
// 列合并
if (columnIndex === 2) {
if (rowIndex % 2 === 0) return { rowspan: 2, colspan: 1 };
else return { rowspan: 0, colspan: 0 };
}
};
</script>
编辑表格
共有三种编辑表格方式:双击编辑/行编辑/列编辑
想要启用单元格编辑必须设置单元格el和isEdit属性
<template>
<div>
<el-tabs type="border-card">
<el-tab-pane label="双击编辑">
设置ifDblclick属性开启双击编辑功能
<SuperProTable
ref="proTable"
:columns="columns"
:data="data"
:ifDblclick="true"
></SuperProTable>
</el-tab-pane>
<el-tab-pane label="行编辑">
需要为每行数据内添加_edit属性,值为true时为可编辑行
<SuperProTable ref="proTable" :columns="columns2" :data="data2">
<template #operation="scope">
<el-button type="primary" link @click="() => scope.row._edit = true">编辑</el-button>
<el-button type="primary" link @click="() => scope.row._edit = false">完成</el-button>
</template>
</SuperProTable>
</el-tab-pane>
<el-tab-pane label="列编辑">
为需要编辑的列添加 edit 属性,并设置为 true,即可开启编辑功能
<SuperProTable ref="proTable" :columns="columns3" :data="data"></SuperProTable>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import { ElTabs, ElTabPane } from 'element-plus'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
])
const columns = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名(可编辑)', el: 'ElInput', isEdit: true },
{ prop: 'address', label: '居住地址' },
])
const data2 = reactive<any[]>([
{
date: Date.now(),
name: '张三',
address: '北京',
_edit: false,
},
{
date: Date.now(),
name: '张三',
address: '北京',
_edit: false,
},
{
date: Date.now(),
name: '张三',
address: '北京',
_edit: false,
},
])
const columns2 = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200, el: 'ElInput', isEdit: true },
{ prop: 'name', label: '姓名', el: 'ElInput', isEdit: true },
{ prop: 'address', label: '居住地址', el: 'ElInput', isEdit: true },
{ prop: 'operation', label: '操作', fixed: 'right' },
])
const columns3 = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名', el: 'ElInput', isEdit: true, edit: true },
{ prop: 'address', label: '居住地址' },
])
</script>
编辑表格校验方法
和在布局表单中一样,通过 required 或 formItemProps:{rules: [验证规则]} 进行校验
可以调用表格的validateTableForm方法进行手动校验
<template>
<div>
<el-tabs type="border-card">
<el-tab-pane label="双击编辑">
<SuperProTable
ref="proTable"
:columns="columns"
:data="data"
:ifDblclick="true"
></SuperProTable>
</el-tab-pane>
<el-tab-pane label="行编辑">
<SuperProTable ref="proTable2" :columns="columns2" :data="data2">
<template #operation="scope">
<el-button
v-if="!scope.row._edit"
type="primary"
link
@click="() => (scope.row._edit = true)"
>
编辑
</el-button>
<el-button v-else type="primary" link @click="handleSuccess(scope)">完成</el-button>
</template>
</SuperProTable>
</el-tab-pane>
<el-tab-pane label="列编辑">
<el-button type="primary" @click="() => (colEdit = !colEdit)">
{{ colEdit ? '保存' : '编辑' }}
</el-button>
<SuperProTable ref="proTable" :columns="columns3" :data="data"></SuperProTable>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, useTemplateRef } from 'vue'
import { ElTabs, ElTabPane } from 'element-plus'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
date: Date.now(),
name: '张三',
number1: 10,
},
{
date: Date.now(),
name: '张三',
number1: 10,
},
{
date: Date.now(),
name: '张三',
number1: 10,
},
])
const columns = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名(可编辑)', el: 'ElInput', isEdit: true, required: true },
{
prop: 'number1',
label: '数值(可编辑)',
el: 'ElInput',
isEdit: true,
formItemProps: {
rules: [
{
validator: (_rule, value, callback) => {
if (Number(value) > 10) {
callback()
} else {
callback('输入值不能小于10')
}
},
trigger: 'change',
},
],
},
},
])
const data2 = reactive<any[]>([
{
date: Date.now(),
name: '张三',
number1: 10,
_edit: false,
},
{
date: Date.now(),
name: '张三',
number1: 10,
_edit: false,
},
{
date: Date.now(),
name: '张三',
number1: 10,
_edit: false,
},
])
const columns2 = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200, el: 'ElInput', isEdit: true },
{ prop: 'name', label: '姓名(可编辑)', el: 'ElInput', isEdit: true, required: true },
{
prop: 'number1',
label: '数值(可编辑)',
el: 'ElInput',
isEdit: true,
formItemProps: {
rules: [
{
validator: (_rule, value, callback) => {
if (Number(value) > 10) {
callback()
} else {
callback('输入值不能小于10')
}
},
trigger: 'change',
},
],
},
},
{ prop: 'operation', label: '操作', fixed: 'right' },
])
const proTable2Ref = useTemplateRef('proTable2')
const handleSuccess = async (scope: any) => {
await proTable2Ref.value.validateTableForm(scope.$index)
scope.row._edit = false
}
const colEdit = ref<boolean>(false)
const columns3 = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200 },
{
prop: 'name',
label: '姓名(可编辑)',
el: 'ElInput',
isEdit: true,
required: true,
edit: colEdit
},
{
prop: 'number1',
label: '数值(可编辑)',
el: 'ElInput',
isEdit: true,
edit: colEdit,
formItemProps: {
rules: [
{
validator: (_rule, value, callback) => {
if (Number(value) > 10) {
callback()
} else {
callback('输入值不能小于10')
}
},
trigger: 'change',
},
],
},
},
])
</script>
表格操作按钮
使用operation插槽来实现
<template>
<div>
<SuperProTable ref="proTable" :columns="columns" :data="data">
<template #operation="scope">
<el-button type="primary" link @click="() => ElMessage.success(`row:${JSON.stringify(scope.row)}`)">
按钮1
</el-button>
<el-button type="primary" link @click="() => ElMessage.success('点击按钮2成功')">
按钮2
</el-button>
</template>
</SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import { ElMessage } from 'element-plus'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
])
const columns = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期' },
{ prop: 'name', label: '姓名' },
{ prop: 'address', label: '居住地址' },
{ prop: 'operation', label: '操作', fixed: 'right' },
])
</script>
表格头部操作按钮插槽
toolButton可控制右侧功能按钮的显示隐藏:传true则显示,false则隐藏,传数组则显示指定的功能按钮,比如['refresh']就只显示刷新按钮
tableHeader插槽可以自定义左侧内容
<template>
<div>
<SuperProTable ref="proTable" :columns="columns" :data="data" :toolButton="['setting']">
<template #tableHeader>
<el-button type="primary" plain >导出用户数据</el-button>
<el-button type="primary" plain>To 子集详情页面</el-button>
<el-button type="danger" plain>批量删除用户</el-button>
</template>
</SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import { ElButton } from 'element-plus'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
])
const columns = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名', width: 200 },
{ prop: 'address', label: '居住地址' },
])
</script>
使用搜索表格
搜索表格支持searchForm和proTable的所有选项
使用requestApi属性获取数据要求:接口返回正常数据格式:
分页: { data: { list: [...], total: ... } }
不分页: { data: [...] }
<template>
<div>
<SuperProTable
ref="proTable"
:field="field"
:columns="columns"
:requestApi="getData"
showSearch
:initParam="form"
:dataCallback="dataCallback"
@search="handleSearch"
>
<template #date>
<ElInput v-model="form.date" placeholder="使用插槽自定义内容" clearable />
</template>
<template #gridSlotComponent>
<SuperGrid :gap="[10, 20]">
<SuperGridItem :span="4">
<el-form-item label="活动时间:">
<div class="flx-center">
<el-date-picker
type="date"
placeholder="选择日期"
v-model="form.activeStart"
style="width: 100%"
></el-date-picker>
<span class="line">-</span>
<el-time-picker
placeholder="选择时间"
v-model="form.activeEnd"
style="width: 100%"
></el-time-picker>
</div>
</el-form-item>
</SuperGridItem>
</SuperGrid>
</template>
</SuperProTable>
</div>
</template>
<script lang="tsx" setup>
import { reactive } from 'vue'
import { ElInput, ElMessage } from 'element-plus'
import { Search } from '@element-plus/icons-vue'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
date: Date.now(),
name: '张三',
address: '北京',
time: Date.now(),
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
])
const form = reactive<any>({
name: '我是默认值',
phone: '13211111',
minAge: '',
maxAge: '',
date: '',
activeStart: '',
activeEnd: '',
})
// 搜索表单配置项
const field = [
{
label: '姓名',
name: 'name',
el: 'ElInput',
formItemProps: {
rules: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
},
componentProps: {
placeholder: '请输入姓名',
clearable: true,
},
scopedSlots: {
prepend: () => (
<el-icon>
<Search />
</el-icon>
),
append: () => <el-button>按钮</el-button>,
},
tooltip: '这是一个提示信息',
span: 2,
},
{
label: '手机号',
name: 'phone',
el: 'ElInput',
componentProps: {
placeholder: '请输入手机号',
clearable: true,
},
required: true,
valueType: 'phone',
span: 2,
},
{
label: '年龄',
name: 'age',
el: 'ElInput',
componentProps: {
placeholder: '请输入',
clearable: true,
},
render: ({ searchParam }: any) => {
// 普通v-model但无法使用修饰符
return (
<div class="flx-center">
<ElInput v-model={searchParam.minAge} placeholder="最小年龄" />
<span class="mr10 ml10">-</span>
<ElInput v-model={searchParam.maxAge} placeholder="最大年龄" />
</div>
)
},
span: 2,
},
{
label: '使用组件插槽',
name: 'date',
slotName: 'date',
span: 2,
},
{
label: '使用布局插槽',
name: 'gridSlot',
slotName: 'gridSlotComponent',
span: 4,
},
]
const columns = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名', width: 200 },
{ prop: 'time', label: '秒' },
{ prop: 'address', label: '居住地址' },
])
const handleSearch = () => {
ElMessage.success('搜索成功')
}
// 模拟网络请求
// 接口返回正常数据格式:
// 分页: { data: { list: [...], total: ... } }
// 不分页: { data: [...] }
const getData = (param: any) => {
console.log(param, "param");
// 第一种:接口返回正确的数据格式
// return new Promise((resolve) => {
// setTimeout(() => {
// resolve({ data: { list: data, total: data.length } })
// }, 1000)
// })
// 第二种:使用回调函数返回正常的数据格式
return new Promise((resolve) => {
setTimeout(() => {
resolve({ data: { listData: data, totalNumber: data.length} })
}, 1000)
})
}
// 修正数据格式
const dataCallback = (data: any) => {
return ({ list: data.listData, total: data.totalNumber })
}
</script>
隐藏搜索表单/表单选项/列数据
列设置isShow属性可以对列进行隐藏
showSearch 为true时显示搜索表单,默认为为false
<template>
<div>
表单数据: {{ form }}
<SuperProTable
ref="proSearchTable"
:field="field"
:columns="columns"
:data="data"
:showSearch="true"
:initParam="initParam"
@search="handleSearch"
>
<template #date="scope">
<ElInput v-model="scope.searchParam.date" placeholder="使用插槽自定义内容" clearable />
</template>
<template #gridSlotComponent="scope">
<SuperGrid :gap="[10, 20]">
<SuperGridItem :span="4">
<el-form-item label="活动时间:">
<div class="flx-center">
<el-date-picker
type="date"
placeholder="选择日期"
v-model="scope.searchParam.activeStart"
style="width: 100%"
></el-date-picker>
<span class="line">-</span>
<el-time-picker
placeholder="选择时间"
v-model="scope.searchParam.activeEnd"
style="width: 100%"
></el-time-picker>
</div>
</el-form-item>
</SuperGridItem>
</SuperGrid>
</template>
</SuperProTable>
</div>
</template>
<script lang="tsx" setup>
import { reactive, useTemplateRef, computed } from 'vue'
import { ElInput, ElMessage } from 'element-plus'
import { Search } from '@element-plus/icons-vue'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
{
date: Date.now(),
name: '张三',
address: '北京',
},
])
const initParam = reactive<any>({
name: '',
phone: '13211111',
phone2: '',
minAge: '',
maxAge: '',
date: '',
activeStart: '',
activeEnd: '',
})
const proSearchTableRef: any = useTemplateRef('proSearchTable')
const form = computed(() => proSearchTableRef.value?.searchParam)
// 搜索表单配置项
const field = [
{
label: '姓名',
name: 'name',
el: 'ElInput',
formItemProps: {
rules: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
},
componentProps: {
placeholder: '请输入姓名',
clearable: true,
},
scopedSlots: {
prepend: () => (
<el-icon>
<Search />
</el-icon>
),
append: () => <el-button>按钮</el-button>,
},
tooltip: '这是一个提示信息',
span: 2,
},
{
label: '手机号',
name: 'phone',
el: 'ElInput',
show: false,
componentProps: {
placeholder: '请输入手机号',
clearable: true,
},
required: true,
valueType: 'phone',
span: 2,
},
{
label: '手机号2',
name: 'phone2',
el: 'ElInput',
show: () => !!form.value?.name,
componentProps: {
placeholder: '请输入手机号',
clearable: true,
},
required: true,
valueType: 'phone',
span: 2,
},
{
label: '年龄',
name: 'age',
el: 'ElInput',
componentProps: {
placeholder: '请输入',
clearable: true,
},
render: ({ searchParam }: any) => {
// 普通v-model但无法使用修饰符
return (
<div class="flx-center">
<ElInput v-model={searchParam.minAge} placeholder="最小年龄" />
<span class="mr10 ml10">-</span>
<ElInput v-model={searchParam.maxAge} placeholder="最大年龄" />
</div>
)
},
span: 2,
},
{
label: '使用组件插槽',
name: 'date',
slotName: 'date',
span: 2,
},
{
label: '使用布局插槽',
name: 'gridSlot',
slotName: 'gridSlotComponent',
span: 4,
},
]
const columns = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200, isShow: false },
{ prop: 'name', label: '姓名', width: 200 },
{ prop: 'address', label: '居住地址' },
])
const handleSearch = () => {
ElMessage.success('搜索成功')
}
</script>
隐藏表格分页
设置pagination为false时隐藏分页
<template>
<div>
<SuperProTable
ref="proTable"
:columns="columns"
:data="data"
:pagination="false"
height="300px"
></SuperProTable>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import type { ColumnProps } from '@super-ui-plus/types'
const data = reactive<any[]>([])
Array.from({ length: 100 }).forEach((_, index) => {
data.push({
date: Date.now(),
name: '张三' + index,
address: '北京',
},)
})
const columns = reactive<ColumnProps<any>[]>([
{ prop: '$index', label: '序号', width: 80 },
{ prop: 'date', label: '日期', width: 200 },
{ prop: 'name', label: '姓名', width: 200 },
{ prop: 'address', label: '居住地址' },
])
</script>
API
table Props
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
columns | 列配置项 | ColumnProps[] | - | - |
data | 静态 table data 数据 | any[] | - | - |
requestApi | 请求表格数据的 api ==> 非必传 | (params: any) => Promise<any> | - | - |
requestAuto | 是否自动执行请求 | boolean | true/false | true |
requestError | 表格 api 请求错误监听回调函数 | (params: any) => void | - | - |
dataCallback | 返回数据的回调函数,可以对数据进行处理 | (data: any) => any | - | - |
pagination | 是否需要分页组件 | boolean | true/false | true |
initParam | 初始化请求参数 | object | - | - |
border | 是否带有纵向边框 | boolean | true/false | true |
toolButton | 是否显示表格功能按钮 | array | boolean | ('refresh' | 'setting' | 'search')[] | boolean | true |
rowKey | 行数据的 Key,用来优化 Table 的渲染; 在使用reserve-selection功能与显示树形数据时,该属性是必填的 | string | - | - |
showSummary | 是否在表格底部显示合计行 | boolean | true/false | false |
sumText | 自定义合计行文本 | string | - | 合计 |
sumNaNText | 自定义合计行文本 | string | - | N/A |
ifDblclick | 是否开启双击单元格编辑 | boolean | true/false | false |
align | 单元格对齐方式 | string | - | center |
height | 表格高度 | string | number | - | - |
ifContinuousMultiple | 是否开启列表数据连续多选 | boolean | true/false | true |
autoScroll | 分页自动滚动到首行 | boolean | true/false | true |
showSearch | 是否显示搜索模块 | boolean | true/false | false |
field | 搜索配置列 | formGridItemProps[] | - | - |
Column Props
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
type | 列类型 | enum | enum | - |
tag | 是否是标签展示 | function | (scope: RenderScope<T>) => any | - |
isShow | 是否显示 | boolean | true/false | true |
isSetting | 是否在 ColSetting 中可配置 | boolean | true/false | true |
isEdit | 是否可编辑 | boolean | true/false | false |
edit | 编辑状态 | boolean | true/false | false |
required | 是否必填 | boolean | true/false | false |
valueType | 内置验证规则类型 | string | - | - |
formItemProps | 透传 el-form-item 属性 | Partial<FormItemProps> | - | - |
el | 渲染组件名称 | strigng | - | - |
enum | 枚举字典数据 | EnumProps[] | - | - |
headerRender | 自定义表头内容渲染(tsx语法) | (scope: HeaderRenderScope<T>) => VNode | HeaderRenderScope | - |
render | 自定义单元格内容渲染(tsx语法) | (scope: RenderScope<T>) => VNode | string | - | - |
format | 内置格式化方式 | ((value: any) => string) | string; | - | - |
sumFilter | 自定义合计内容 | (value: any, param: SummaryMethodProps) => string | SummaryMethodProps | - |
sumDataPrefix | 合计数据前缀 | strigng | - | - |
_children | 多级表头 | ColumnProps<T>[] | - | - |
align | 单元格对齐方式 | string | - | center |
table Slots
插槽名 | 说明 |
---|---|
default | 表格默认内容插槽 |
tableHeader | 表格上方插槽 |
toolButton | 右侧工具扩展插槽 |
append | 插入表格最后一行之后的插槽 |
pagination | 分页组件插槽 |
searchForm | 搜索表单插槽 |
formGridSlots/formGridItemSlots | 搜索表单元素内容插槽 |
table Colum Slots
插槽名 | 说明 |
---|---|
header | 自定义表头的内容 |
expand | 展开列的自定义内容 |