表格渲染
单元格有 4 种自定义方式渲染:
render:完全自定义单元格整体渲染,支持 h 函数、jsx/tsxrenderHTML:返回 HTML 字符串渲染单元格slots:根据配置项的prop生成对应的单元格插槽,生成规则为{prop},和render函数功能一致formatValue:通过formatter函数对单元格数据进行格式化
表头有 3 种自定义方式进行渲染:
render:完全自定义表头整体渲染,支持 h 函数、jsx/tsxrenderHTML:返回 HTML 字符串渲染表头slots:根据配置项的prop生成对应的表头插槽,生成规则为{prop}-header,与render函数功能一致
如果同时存在多个方式,只生效一个,优先级从高到低(单元格和表头同理)。
除此之外,Teek 内置了部分常用的单元格组件,通过 el 配置组件名称。
单元格组件
通过在 columns 中配置 el 属性,可以使用内置的组件渲染单元格数据。
通过 elProps 配置对应 el 属性对应的组件 Props 属性。
通过 elSlots 配置对应 el 属性对应的组件 Slots 属性。
<script setup lang="ts">
import type { TableColumn } from "@/components/pro/table";
import { h } from "vue";
import { ElEmpty, ElIcon } from "element-plus/es";
import { ProTable } from "@/components/pro/table";
import { Link } from "@element-plus/icons-vue";
const data = [
{
copy: "张三",
tag: 0,
progress: 10,
link: "按钮",
img: "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
},
{ copy: "李四", tag: 1, progress: 30, link: "按钮", img: "" },
{ copy: "王五", tag: 1, progress: 50, link: "按钮", img: "" },
{
copy: "孙六",
tag: 0,
progress: 80,
link: "按钮",
img: "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
},
];
const columns: TableColumn[] = [
{ type: "index", label: "#", width: 60 },
{ prop: "copy", label: "用户姓名", el: "copy" },
{
prop: "tag",
label: "标签",
el: "el-tag",
elProps: value => ({
type: value === 0 ? "success" : "info",
}),
elSlots: {
default: ({ value }) => (value === 0 ? "开启" : "关闭"),
},
},
{
prop: "progress",
label: "进度",
el: "el-progress",
elProps: value => ({
status: value === 30 ? "success" : "warning",
}),
elSlots: {
default: ({ value }) => ((value as number) > 30 ? "高" : "低"),
},
},
{ prop: "link", label: "点击跳转", el: "el-link", icon: () => h(ElIcon, null, () => h(Link)) },
{
prop: "img",
label: "图片",
el: "el-image",
elSlots: {
error: () => h(ElEmpty, { description: "图片坏了" }),
},
},
];
</script>
<template>
<ProTable :columns="columns" :data="data" border />
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
自定义单元格渲染(render)
通过在单个 column 中配置 render 属性,返回 VNode 或 string 来自定义单元格渲染。
这里演示通过 h 函数创建 VNode。
<script setup lang="ts">
import type { TableColumn } from "@/components/pro/table";
import { h } from "vue";
import { ElButton, ElMessage, ElProgress, ElTag } from "element-plus";
import { ProTable } from "@/components/pro/table";
const data = [
{ username: "张三", gender: 1, progress: 20, birthday: "2023-01-01" },
{ username: "李四", gender: 2, progress: 40, birthday: "2023-02-01" },
{ username: "王五", gender: 1, progress: 60, birthday: "2023-03-01" },
];
const columns: TableColumn[] = [
{ type: "index", label: "#", width: 60 },
{
prop: "username",
label: "用户姓名",
render: ({ value }) =>
h(
ElButton,
{
type: "primary",
link: true,
onClick: () => ElMessage.success("我是通过 h 语法渲染的内容"),
},
{
default: () => value,
}
),
},
{
prop: "gender",
label: "性别",
el: "el-tag",
options: async () => {
return [
{ label: "男", value: 1 },
{ label: "女", value: 2 },
];
},
render: ({ value, displayValue }) =>
h(
ElTag,
{ type: value === 1 ? "success" : "danger" },
{
default: () => displayValue,
}
),
// 通过 elProps 传递属性
elProps: {
closable: true,
},
},
{
prop: "progress",
label: "进度",
el: "el-progress",
render: ({ value }) => h(ElProgress, { percentage: value as number }),
},
{ prop: "birthday", label: "生日", render: ({ value }) => h("span", {}, `render 渲染:${value}`) },
];
</script>
<template>
<ProTable :columns="columns" :data="data">
<template #birthday="{ value }">
<!-- 插槽优先级比 render 低,会被 render 覆盖 -->
{{ value }}
</template>
</ProTable>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
自定义单元格渲染(jsx/tsx)
除了 h 函数,你还可以使用 jsx 或 tsx 自定义单元格渲染。
警告
使用 jsx 或 tsx 时,请在 script 上将 lang=ts 改为 lang=tsx。
<script setup lang="tsx"><script setup lang="tsx">
import type { TableColumn } from "@/components/pro/table";
import { h, ref, withModifiers } from "vue";
import { ElButton, ElMessage, ElMessageBox, ElProgress, ElSwitch, ElTag } from "element-plus";
import { ProTable } from "@/components/pro/table";
const data = [
{ username: "张三", status: 1, progress: 20, birthday: "2023-01-01" },
{ username: "李四", status: 0, progress: 40, birthday: "2023-02-01" },
{ username: "王五", status: 1, progress: 60, birthday: "2023-03-01" },
];
const switchUserStatus = ref(false);
const columns: TableColumn[] = [
{ type: "index", label: "#", width: 60 },
{
prop: "username",
label: "用户姓名",
render: ({ value }) => {
return (
<ElButton
type="primary"
link
onClick={withModifiers(() => ElMessage.success("我是通过 tsx 语法渲染的内容"), ["stop"])}
>
{value}
</ElButton>
);
},
},
{
prop: "status",
label: "用户状态",
options: [
{ userLabel: "启用", userStatus: 1 },
{ userLabel: "禁用", userStatus: 0 },
],
optionField: { label: "userLabel", value: "userStatus" },
render: ({ value, row }) => {
return (
<>
{switchUserStatus.value ? (
<ElSwitch
model-value={value}
active-text={value ? "启用" : "禁用"}
active-value={1}
inactive-value={0}
{...{
onClick: async () => {
await ElMessageBox.confirm("确定要修改吗?", "提示").then(() => {
row.status === 0 ? (row.status = 1) : (row.status = 0);
});
ElMessage.success(`切换【${row.username}】用户状态成功`);
},
}}
/>
) : (
<ElTag type={value ? "success" : "danger"}>{value ? "启用" : "禁用"}</ElTag>
)}
</>
);
},
},
{
prop: "progress",
label: "进度",
el: "el-progress",
render: ({ value }) => <ElProgress percentage={value as number} />,
},
{ prop: "birthday", label: "生日" },
];
</script>
<template>
<ProTable :columns="columns" :data="data">
<template #head-left>
<ElButton type="primary" @click="switchUserStatus = !switchUserStatus">切换用户状态</ElButton>
</template>
</ProTable>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
自定义单元格渲染(renderHtml)
如果你只想对内容进行替换,可以使用 renderHtml 属性返回一个可信的 HTML 字符串。
<script setup lang="ts">
import type { TableColumn } from "@/components/pro/table";
import { ProTable } from "@/components/pro/table";
const data = [
{ username: "张三", gender: 1, idCard: "805839158256013232", birthday: "2023-01-01" },
{ username: "李四", gender: 2, idCard: "824440124728046271", birthday: "2023-02-01" },
{ username: "王五", gender: 1, idCard: "026454951166840353", birthday: "2023-03-01" },
];
const columns: TableColumn[] = [
{ type: "index", label: "#", width: 60 },
{
prop: "username",
label: "用户姓名",
renderHTML: ({ value }) => `<span style="color: red">${value}</span>`,
},
{
prop: "gender",
label: "性别",
options: [
{ label: "男", value: 1, tagType: "primary" },
{ label: "女", value: 2, tagType: "warning" },
],
renderHTML: ({ value }) => `<span style="color: #395AE3">${value}-自定义</span>`,
},
{
prop: "idCard",
label: "身份证号",
filter: true,
renderHTML: ({ value }) => {
return `<input style="border:1px solid #dd5c27;width:80px;padding:0 10px;" value=${value} />`;
},
},
{
prop: "birthday",
label: "生日",
renderHTML: ({ value }) => {
return `日期:<span style="color: #e68a00">${value}</span>`;
},
},
];
</script>
<template>
<ProTable :columns="columns" :data="data" />
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
自定义单元格渲染(插槽)
Teek 会将单个 column 的 prop 属性生成插槽,因此你也可以使用插槽自定义单元格渲染。
生成插槽的规则为当前 prop 的值,假设一个 column 的 prop 为 username,那么插槽为 username。
<script setup lang="ts">
import type { TableColumn } from "@/components/pro/table";
import { ElButton, ElMessage, ElProgress, ElTag } from "element-plus";
import { ProTable } from "@/components/pro/table";
const data = [
{ username: "张三", gender: 1, progress: 20, birthday: "2023-01-01" },
{ username: "李四", gender: 2, progress: 40, birthday: "2023-02-01" },
{ username: "王五", gender: 1, progress: 60, birthday: "2023-03-01" },
];
const columns: TableColumn[] = [
{ type: "index", label: "#", width: 60 },
{ prop: "username", label: "用户姓名" },
{
prop: "gender",
label: "性别",
el: "el-tag",
options: async () => {
return [
{ label: "男", value: 1 },
{ label: "女", value: 2 },
];
},
// 通过 elProps 传递属性
elProps: {
closable: true,
},
},
{
prop: "progress",
label: "进度",
el: "el-progress",
},
{ prop: "birthday", label: "生日" },
];
const handleClick = () => {
ElMessage.success("我是通过作用域插槽渲染的内容");
};
</script>
<template>
<ProTable :columns="columns" :data="data">
<template #username="{ row }">
<el-button @click="handleClick">{{ row.username }}</el-button>
</template>
<template #gender="{ row, displayValue }">
<el-tag :type="row.gender === 1 ? 'success' : 'danger'">{{ displayValue }}</el-tag>
</template>
<template #progress="{ value }">
<el-progress :percentage="value as number" />
</template>
</ProTable>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
自定义单元格渲染(formatValue)
如果你只想对内容进行格式化,如添加一些前缀或者后缀内容,可以使用 formatValue 配置项。
<script setup lang="ts">
import type { TableColumn } from "@/components/pro/table";
import { ProTable } from "@/components/pro/table";
const data = [
{ username: "张三", gender: 1, idCard: "805839158256013232", birthday: "2023-01-01" },
{ username: "李四", gender: 2, idCard: "824440124728046271", birthday: "2023-02-01" },
{ username: "王五", gender: 1, idCard: "026454951166840353", birthday: "2023-03-01" },
];
const columns: TableColumn[] = [
{ type: "index", label: "#", width: 60 },
{ prop: "username", label: "用户姓名", renderHTML: ({ value }) => `<span style="color: red">${value}</span>` },
{
prop: "gender",
label: "性别",
el: "el-tag",
options: [
{ label: "男", value: 1, tagType: "primary" },
{ label: "女", value: 2, tagType: "warning" },
],
formatValue: (value, { column }) => `${value}-${column.prop}` + "-自定义" || "",
},
{
prop: "idCard",
label: "身份证号",
filter: true,
formatValue: value => (value as string)?.replace(/\d{4}/, "****"),
},
{ prop: "birthday", label: "生日", formatValue: value => `日期:${value}` },
];
</script>
<template>
<ProTable :columns="columns" :data="data" />
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
自定义表头渲染(renderHeader)
通过在单个 column 中配置 renderHeader 属性,返回 VNode 或 string 来自定义表头渲染。
<script setup lang="ts">
import type { TableColumn } from "@/components/pro/table";
import { h } from "vue";
import { ElButton, ElMessage, ElProgress, ElTag } from "element-plus";
import { ProTable } from "@/components/pro/table";
const data = [
{ username: "张三", gender: 1, progress: 20, birthday: "2023-01-01" },
{ username: "李四", gender: 2, progress: 40, birthday: "2023-02-01" },
{ username: "王五", gender: 1, progress: 60, birthday: "2023-03-01" },
];
const columns: TableColumn[] = [
{ type: "index", label: "#", width: 60 },
{
prop: "username",
label: "用户姓名",
renderHeader: ({ column }) =>
h(
ElButton,
{
type: "primary",
onClick: () => ElMessage.success("我是通过 h 语法渲染的表头"),
},
{
default: () => `h ${column.label}`,
}
),
},
{
prop: "gender",
label: "性别",
el: "el-tag",
options: async () => {
return [
{ label: "男", value: 1 },
{ label: "女", value: 2 },
];
},
renderHeader: ({ column }) =>
h(
ElTag,
{ type: "danger" },
{
default: () => column.label,
}
),
// 通过 elProps 传递属性
elProps: {
closable: true,
},
},
{
prop: "progress",
label: "进度",
el: "el-progress",
renderHeader: () => h(ElProgress, { percentage: 90 }),
},
{ prop: "birthday", label: "生日", renderHeader: ({ column }) => h("span", {}, `h 渲染:${column.label}`) },
];
</script>
<template>
<ProTable :columns="columns" :data="data" />
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
自定义表头渲染(jsx/tsx)
除了 h 函数,你还可以使用 jsx 或 tsx 自定义表头渲染。
警告
使用 jsx 或 tsx 时,请在 script 上将 lang=ts 改为 lang=tsx。
<script setup lang="tsx"><script setup lang="tsx">
import type { TableColumn } from "@/components/pro/table";
import { withModifiers } from "vue";
import { ElButton, ElMessage, ElProgress, ElTag } from "element-plus";
import { ProTable } from "@/components/pro/table";
const data = [
{ username: "张三", gender: 1, progress: 20, birthday: "2023-01-01" },
{ username: "李四", gender: 2, progress: 40, birthday: "2023-02-01" },
{ username: "王五", gender: 1, progress: 60, birthday: "2023-03-01" },
];
const columns: TableColumn[] = [
{ type: "index", label: "#", width: 60 },
{
prop: "username",
label: "用户姓名",
renderHeader: ({ column }) => {
return (
<ElButton
type="primary"
link
onClick={withModifiers(() => ElMessage.success("我是通过 tsx 语法渲染的表头"), ["stop"])}
>
{column.label}
</ElButton>
);
},
},
{
prop: "gender",
label: "性别",
el: "el-tag",
options: async () => {
return [
{ label: "男", value: 1 },
{ label: "女", value: 2 },
];
},
renderHeader: ({ column }) => {
return <ElTag type="info">{column.label}</ElTag>;
},
// 通过 elProps 传递属性
elProps: {
closable: true,
},
},
{
prop: "progress",
label: "进度",
el: "el-progress",
renderHeader: () => <ElProgress percentage={90} />,
},
{ prop: "birthday", label: "生日", renderHeader: ({ column }) => <span>tsx 渲染:${column.label}</span> },
];
</script>
<template>
<ProTable :columns="columns" :data="data" />
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
自定义表头渲染(renderHeaderHTML)
如果你只想对内容进行替换,可以使用 renderHeaderHTML 属性返回一个可信的 HTML 字符串进行表头内容渲染。
<script setup lang="ts">
import type { TableColumn } from "@/components/pro/table";
import { ProTable } from "@/components/pro/table";
const data = [
{ username: "张三", gender: 1, progress: 20, birthday: "2023-01-01" },
{ username: "李四", gender: 2, progress: 40, birthday: "2023-02-01" },
{ username: "王五", gender: 1, progress: 60, birthday: "2023-03-01" },
];
const columns: TableColumn[] = [
{ type: "index", label: "#", width: 60 },
{
prop: "username",
label: "用户姓名",
renderHeaderHTML: ({ column }) => `<span style="color: red;">${column.label}</span>`,
},
{
prop: "gender",
label: "性别",
el: "el-tag",
options: async () => {
return [
{ label: "男", value: 1 },
{ label: "女", value: 2 },
];
},
renderHeaderHTML: ({ column }) => `<span style="color: #395AE3;">${column.label}</span>`,
},
{
prop: "progress",
label: "进度",
el: "el-progress",
renderHeaderHTML: ({ column }) => `<span style="color: #dd5c27;">${column.label}</span>`,
},
{
prop: "birthday",
label: "生日",
renderHeaderHTML: ({ column }) => `<span style="color: #e68a00;">${column.label}</span>`,
},
];
</script>
<template>
<ProTable :columns="columns" :data="data" />
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
自定义表头渲染(插槽)
Teek 会将单个 column 的 prop 属性根据规则生成表头插槽,因此你也可以使用表头插槽自定义表头渲染。
生成插槽的规则为当前 prop 的值 + -header,假设一个 column 的 prop 为 username,那么表头插槽为 username-header。
除了使用 prop 生成插槽,Teek 还提供了 header-before 和 header-after 两个 全局 表头插槽,分别在表头插槽之前和之后插入内容。
<script setup lang="ts">
import type { TableColumn } from "@/components/pro/table";
import { h } from "vue";
import { ElButton, ElMessage, ElProgress, ElTag } from "element-plus";
import { ProTable } from "@/components/pro/table";
const data = [
{ username: "张三", gender: 1, progress: 20, birthday: "2023-01-01" },
{ username: "李四", gender: 2, progress: 40, birthday: "2023-02-01" },
{ username: "王五", gender: 1, progress: 60, birthday: "2023-03-01" },
];
const columns: TableColumn[] = [
{ type: "index", label: "#", width: 60 },
{ prop: "username", label: "用户姓名" },
{
prop: "gender",
label: "性别",
el: "el-tag",
options: async () => {
return [
{ label: "男", value: 1 },
{ label: "女", value: 2 },
];
},
},
{
prop: "progress",
label: "进度",
el: "el-progress",
},
{ prop: "birthday", label: "生日" },
];
</script>
<template>
<ProTable :columns="columns" :data="data">
<template #header-before>pre</template>
<template #username-header="{ column }">
<el-button type="primary" @click="ElMessage.success('我是通过作用域插槽渲染的表头')">
slot {{ column.label }}
</el-button>
</template>
<template #gender-header="{ column }">
<el-tag type="warning">{{ column.label }}</el-tag>
</template>
<template #progress-header>
<el-progress :percentage="100" />
</template>
<template #birthday-header="{ column }">slot 渲染:{{ column.label }}</template>
<template #header-after>pro</template>
</ProTable>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58