FxTable 表格
用于展示行列数据。自实现、不依赖任何 UI 框架,支持列配置、自定义单元格/表头渲染、斑马纹、纵向边框、table-layout 等。
FxTable 属于 @fx/components(UI 框架无关的通用组件)。
基础用法
通过 FxTableColumn 配置列,data 提供行数据。
vue
<template>
<FxTable :data="tableData" style="width: 100%">
<FxTableColumn prop="date" label="Date" width="180" />
<FxTableColumn prop="name" label="Name" width="180" />
<FxTableColumn prop="address" label="Address" />
</FxTable>
</template>
<script setup lang="ts">
import { FxTable, FxTableColumn } from '@fx/components'
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]
</script>1
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
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
斑马纹
使用 stripe 属性启用斑马纹。
vue
<template>
<FxTable :data="tableData" stripe style="width: 100%">
<FxTableColumn prop="date" label="Date" width="180" />
<FxTableColumn prop="name" label="Name" width="180" />
<FxTableColumn prop="address" label="Address" />
</FxTable>
</template>
<script setup lang="ts">
import { FxTable, FxTableColumn } from '@fx/components'
const tableData = [
{ date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
]
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
边框
使用 border 属性启用纵向边框。
vue
<template>
<FxTable :data="tableData" border style="width: 100%">
<FxTableColumn prop="date" label="Date" width="180" />
<FxTableColumn prop="name" label="Name" width="180" />
<FxTableColumn prop="address" label="Address" />
</FxTable>
</template>
<script setup lang="ts">
import { FxTable, FxTableColumn } from '@fx/components'
const tableData = [
{ date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
]
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
表格布局
通过 table-layout 控制列宽算法:fixed(默认,列宽固定、溢出省略)与 auto(列宽随内容自适应)。
vue
<template>
<div style="display: flex; flex-direction: column; gap: 24px">
<div>
<h4 style="margin: 0 0 8px">table-layout: fixed(列宽固定,溢出省略)</h4>
<FxTable :data="tableData" table-layout="fixed" style="width: 100%">
<FxTableColumn prop="date" label="Date" width="120" />
<FxTableColumn prop="name" label="Name" width="120" />
<FxTableColumn prop="address" label="Address" />
</FxTable>
</div>
<div>
<h4 style="margin: 0 0 8px">table-layout: auto(列宽随内容)</h4>
<FxTable :data="tableData" table-layout="auto" style="width: 100%">
<FxTableColumn prop="date" label="Date" />
<FxTableColumn prop="name" label="Name" />
<FxTableColumn prop="address" label="Address" />
</FxTable>
</div>
</div>
</template>
<script setup lang="ts">
import { FxTable, FxTableColumn } from '@fx/components'
const tableData = [
{ date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
]
</script>1
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
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
自定义列内容
使用 FxTableColumn 的 default 插槽自定义单元格,参数为 { row, column, $index }。
vue
<template>
<FxTable :data="tableData" style="width: 100%">
<FxTableColumn label="Date" width="180">
<template #default="scope">
<div style="display: flex; align-items: center">
<FxIcon name="ep:timer" />
<span style="margin-left: 10px">{{ scope.row.date }}</span>
</div>
</template>
</FxTableColumn>
<FxTableColumn label="Name" width="180">
<template #default="scope">
<FxPopover effect="light" trigger="hover" placement="top" width="auto">
<template #content>
<div>name: {{ scope.row.name }}</div>
<div>address: {{ scope.row.address }}</div>
</template>
<template #reference>
<FxTag>{{ scope.row.name }}</FxTag>
</template>
</FxPopover>
</template>
</FxTableColumn>
<FxTableColumn label="Operations">
<template #default="scope">
<FxBtn
link
type="primary"
size="small"
@click="handleEdit(scope.$index, scope.row)"
>
Edit
</FxBtn>
<FxBtn
link
type="danger"
size="small"
@click="handleDelete(scope.$index, scope.row)"
>
Delete
</FxBtn>
</template>
</FxTableColumn>
</FxTable>
</template>
<script lang="ts" setup>
import { FxTable, FxTableColumn, FxTag, FxBtn, fxMsg } from '@fx/components'
import { FxIcon } from '@fx-core/icon'
interface User {
date: string
name: string
address: string
}
const handleEdit = (index: number, row: User) => {
fxMsg(`Edit: ${index} - ${row.name}`)
}
const handleDelete = (index: number, row: User) => {
fxMsg(`Delete: ${index} - ${row.name}`)
}
const tableData: User[] = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]
</script>1
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
83
84
85
86
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
83
84
85
86
自定义表头
使用 header 插槽自定义表头,参数为 { column, $index }。
vue
<template>
<FxTable :data="filterTableData" style="width: 100%">
<FxTableColumn label="Date" prop="date" />
<FxTableColumn label="Name" prop="name" />
<FxTableColumn align="right">
<template #header>
<FxInput
v-model="search"
size="small"
placeholder="Type to search"
/>
</template>
<template #default="scope">
<FxBtn
link
type="primary"
size="small"
@click="handleEdit(scope.$index, scope.row)"
>
Edit
</FxBtn>
<FxBtn
link
type="danger"
size="small"
@click="handleDelete(scope.$index, scope.row)"
>
Delete
</FxBtn>
</template>
</FxTableColumn>
</FxTable>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue'
import { FxTable, FxTableColumn, FxInput, FxBtn, fxMsg } from '@fx/components'
interface User {
date: string
name: string
address: string
}
const search = ref('')
const filterTableData = computed(() =>
tableData.filter(
(data) =>
!search.value ||
data.name.toLowerCase().includes(search.value.toLowerCase()),
),
)
const handleEdit = (index: number, row: User) => {
fxMsg(`Edit: ${index} - ${row.name}`)
}
const handleDelete = (index: number, row: User) => {
fxMsg(`Delete: ${index} - ${row.name}`)
}
const tableData: User[] = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'John',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Morgan',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Jessy',
address: 'No. 189, Grove St, Los Angeles',
},
]
</script>1
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
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
排序
对 FxTableColumn 设置 sortable 属性可启用排序,点击表头在「升序 → 降序 → 取消」之间循环切换。通过 default-sort 设置初始排序,sort-orders 可自定义切换顺序。
vue
<template>
<FxTable
:data="tableData"
:default-sort="{ prop: 'date', order: 'descending' }"
style="width: 100%"
>
<FxTableColumn prop="date" label="Date" sortable width="180" />
<FxTableColumn prop="name" label="Name" width="180" />
<FxTableColumn prop="address" label="Address" :formatter="formatter" />
</FxTable>
</template>
<script setup lang="ts">
import { FxTable, FxTableColumn } from '@fx/components'
import type { TableColumnCtx } from '@fx/components'
interface User {
date: string
name: string
address: string
}
const formatter = (row: User, _column: TableColumnCtx<User>) => row.address
const tableData: User[] = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]
</script>1
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
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
筛选
对 FxTableColumn 设置 filters(筛选项数组)与 filter-method(过滤函数)启用筛选。filter-multiple 控制单选/多选(默认多选),column-key 用于 clearFilter 精确定位列。
vue
<template>
<div style="margin-bottom: 12px">
<FxBtn style="margin-right: 8px" @click="resetDateFilter">Reset date filter</FxBtn>
<FxBtn @click="clearFilter">Reset all filters</FxBtn>
</div>
<FxTable ref="tableRef" row-key="date" :data="tableData" style="width: 100%">
<FxTableColumn
prop="date"
label="Date"
sortable
width="180"
column-key="date"
:filters="dateFilters"
:filter-method="filterHandler"
/>
<FxTableColumn prop="name" label="Name" width="180" />
<FxTableColumn prop="address" label="Address" :formatter="formatter" />
<FxTableColumn
prop="tag"
label="Tag"
width="100"
column-key="tag"
:filters="tagFilters"
:filter-method="filterTag"
filter-placement="bottom-end"
>
<template #default="scope">
<FxTag :type="scope.row.tag === 'Home' ? 'primary' : 'success'">
{{ scope.row.tag }}
</FxTag>
</template>
</FxTableColumn>
</FxTable>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { FxTable, FxTableColumn, FxBtn, FxTag } from '@fx/components'
import type { TableColumnCtx } from '@fx/components'
interface User {
date: string
name: string
address: string
tag: string
}
const tableRef = ref<InstanceType<typeof FxTable>>()
const resetDateFilter = () => {
tableRef.value!.clearFilter(['date'])
}
const clearFilter = () => {
tableRef.value!.clearFilter()
}
const formatter = (row: User) => row.address
const filterTag = (value: string, row: User) => row.tag === value
const filterHandler = (value: string, row: User, column: TableColumnCtx<User>) => {
const property = column.property as keyof User
return row[property] === value
}
const dateFilters = [
{ text: '2016-05-01', value: '2016-05-01' },
{ text: '2016-05-02', value: '2016-05-02' },
{ text: '2016-05-03', value: '2016-05-03' },
{ text: '2016-05-04', value: '2016-05-04' },
]
const tagFilters = [
{ text: 'Home', value: 'Home' },
{ text: 'Office', value: 'Office' },
]
const tableData: User[] = [
{ date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', tag: 'Home' },
{ date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', tag: 'Office' },
{ date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', tag: 'Home' },
{ date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', tag: 'Office' },
]
</script>1
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
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
多选
设置 FxTableColumn 的 type="selection" 启用多选列。监听 selection-change 获取选中行;通过 ref 调用 toggleRowSelection / clearSelection / toggleAllSelection / getSelectionRows。
vue
<template>
<FxTable
ref="multipleTableRef"
:data="tableData"
row-key="id"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<FxTableColumn type="selection" :selectable="selectable" width="55" />
<FxTableColumn label="Date" width="120">
<template #default="scope">{{ scope.row.date }}</template>
</FxTableColumn>
<FxTableColumn prop="name" label="Name" width="120" />
<FxTableColumn prop="address" label="Address" />
</FxTable>
<div style="margin-top: 20px">
<FxBtn @click="toggleSelection([tableData[1]!, tableData[2]!])">
Toggle selection status of second and third rows
</FxBtn>
<FxBtn @click="toggleSelection([tableData[1]!, tableData[2]!], false)">
Toggle selection status based on selectable
</FxBtn>
<FxBtn @click="toggleSelection()">Clear selection</FxBtn>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { FxTable, FxTableColumn, FxBtn } from '@fx/components'
interface User {
id: number
date: string
name: string
address: string
}
const multipleTableRef = ref<InstanceType<typeof FxTable>>()
const multipleSelection = ref<User[]>([])
const selectable = (row: User) => ![1, 2].includes(row.id)
const toggleSelection = (rows?: User[], ignoreSelectable?: boolean) => {
if (rows) {
rows.forEach((row) => {
multipleTableRef.value!.toggleRowSelection(row, undefined, ignoreSelectable)
})
} else {
multipleTableRef.value!.clearSelection()
}
}
const handleSelectionChange = (val: User[]) => {
multipleSelection.value = val
}
const tableData: User[] = [
{ id: 1, date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ id: 2, date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ id: 3, date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ id: 4, date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ id: 5, date: '2016-05-08', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ id: 6, date: '2016-05-06', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ id: 7, date: '2016-05-07', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
]
</script>1
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
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
单选(当前行高亮)
设置 highlight-current-row 启用单选高亮,点击行触发 current-change。通过 ref 调用 setCurrentRow 程序化设置当前行,或用 current-row-key + row-key 定位。
vue
<template>
<FxTable
ref="singleTableRef"
:data="tableData"
highlight-current-row
style="width: 100%"
@current-change="handleCurrentChange"
>
<FxTableColumn type="index" width="50" />
<FxTableColumn prop="date" label="Date" width="120" />
<FxTableColumn prop="name" label="Name" width="120" />
<FxTableColumn prop="address" label="Address" />
</FxTable>
<div style="margin-top: 20px">
<FxBtn @click="setCurrent(tableData[1]!)">Select second row</FxBtn>
<FxBtn @click="setCurrent()">Clear selection</FxBtn>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { FxTable, FxTableColumn, FxBtn } from '@fx/components'
interface User {
date: string
name: string
address: string
}
const currentRow = ref<User>()
const singleTableRef = ref<InstanceType<typeof FxTable>>()
const setCurrent = (row?: User) => {
singleTableRef.value!.setCurrentRow(row)
}
const handleCurrentChange = (val: User | null) => {
currentRow.value = val ?? undefined
}
const tableData: User[] = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]
</script>1
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
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
可选树(父子联动 / checkStrictly)
树形数据下,tree-props.check-strictly 控制父子节点选择是否联动:true 时父子独立(选父不选子),false 时父选则子全选。selectable 函数控制单行是否可选。
vue
<template>
<div style="margin-bottom: 12px">
<FxRadioGroup v-model="treeProps.checkStrictly">
<FxRadio :value="true">true(父子独立,不联动)</FxRadio>
<FxRadio :value="false">false(父子联动)</FxRadio>
</FxRadioGroup>
</div>
<FxTable
:data="tableData"
:tree-props="treeProps"
row-key="id"
default-expand-all
style="width: 100%"
>
<FxTableColumn type="selection" width="55" :selectable="selectable" />
<FxTableColumn prop="date" label="Date" />
<FxTableColumn prop="name" label="Name" />
<FxTableColumn prop="address" label="Address" />
</FxTable>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import { FxTable, FxTableColumn, FxRadioGroup, FxRadio } from '@fx/components'
interface User {
id: number
date: string
name: string
address: string
hasChildren?: boolean
children?: User[]
}
const treeProps = reactive({
checkStrictly: false,
})
const selectable = (row: User) => ![1, 31].includes(row.id)
const tableData: User[] = [
{
id: 1,
date: '2016-05-02',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 2,
date: '2016-05-04',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 3,
date: '2016-05-01',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
children: [
{
id: 31,
date: '2016-05-01',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 32,
date: '2016-05-01',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 33,
date: '2016-05-01',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
],
},
{
id: 4,
date: '2016-05-03',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
]
</script>1
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
83
84
85
86
87
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
83
84
85
86
87
溢出提示
对 FxTableColumn 设置 show-overflow-tooltip,单元格内容溢出时 hover 显示完整内容。tooltip-formatter 可自定义 tooltip 内容。
vue
<template>
<FxTable :data="tableData" style="width: 100%">
<FxTableColumn type="selection" width="55" />
<FxTableColumn label="Date" width="120">
<template #default="scope">{{ scope.row.date }}</template>
</FxTableColumn>
<FxTableColumn prop="name" label="Name" width="120" />
<FxTableColumn
prop="address"
label="use show-overflow-tooltip"
width="240"
show-overflow-tooltip
/>
<FxTableColumn prop="address" label="address" />
</FxTable>
</template>
<script lang="ts" setup>
import { FxTable, FxTableColumn } from '@fx/components'
interface User {
date: string
name: string
address: string
}
const tableData: User[] = [
{
date: '2016-05-04',
name: 'Aleyna Kutzner',
address: 'Lohrbergstr. 86c, Süd Lilli, Saarland',
},
{
date: '2016-05-03',
name: 'Helen Jacobi',
address: '760 A Street, South Frankfield, Illinois',
},
{
date: '2016-05-02',
name: 'Brandon Deckert',
address: 'Arnold-Ohletz-Str. 41a, Alt Malinascheid, Thüringen',
},
{
date: '2016-05-01',
name: 'Margie Smith',
address: '23618 Windsor Drive, West Ricardoview, Idaho',
},
]
</script>1
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
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
vue
<template>
<FxTable
:data="tableData"
show-overflow-tooltip
:tooltip-formatter="tableRowFormatter"
style="width: 100%"
>
<FxTableColumn
prop="address"
label="extends table formatter"
width="240"
/>
<FxTableColumn
prop="tags"
label="formatter object"
width="240"
:tooltip-formatter="({ row }) => row.tags.join(', ')"
>
<template #default="{ row }">
<FxTag
v-for="tag in row.tags"
:key="tag"
class="tag-item"
type="primary"
>
{{ tag }}
</FxTag>
</template>
</FxTableColumn>
<FxTableColumn
prop="url"
label="with vnode"
width="240"
:tooltip-formatter="withVNode"
/>
</FxTable>
</template>
<script lang="ts" setup>
import { h } from 'vue'
import {
FxTable,
FxTableColumn,
FxTag,
FxLink,
} from '@fx/components'
interface TableData {
address: string
tags: string[]
url: string
}
const tableData: TableData[] = [
{
address: 'Lohrbergstr. 86c, Süd Lilli, Saarland',
tags: ['Office', 'Home', 'Park', 'Garden'],
url: 'https://example.com/issues',
},
{
address: '760 A Street, South Frankfield, Illinois',
tags: ['error', 'warning', 'success', 'info'],
url: 'https://example.com/pulls',
},
{
address: 'Arnold-Ohletz-Str. 41a, Alt Malinascheid, Thüringen',
tags: ['one', 'two', 'three', 'four', 'five'],
url: 'https://example.com/discussions',
},
{
address: '23618 Windsor Drive, West Ricardoview, Idaho',
tags: ['blue', 'white', 'dark', 'gray', 'red', 'bright'],
url: 'https://example.com/actions',
},
]
const tableRowFormatter = (data: {
row: TableData
cellValue: unknown
}) => {
return `${data.cellValue}: table formatter`
}
const withVNode = (data: { row: TableData; cellValue: unknown }) => {
const href = data.cellValue as string
return h(FxLink, { type: 'primary', href }, () =>
h('span', null, href),
)
}
</script>
<style scoped>
.tag-item + .tag-item {
margin-left: 5px;
}
</style>1
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
自定义序号
type="index" 列显示行序号,index 属性传函数可自定义序号算法。
vue
<template>
<FxTable :data="tableData" style="width: 100%">
<FxTableColumn type="index" :index="indexMethod" />
<FxTableColumn prop="date" label="Date" width="180" />
<FxTableColumn prop="name" label="Name" width="180" />
<FxTableColumn prop="address" label="Address" />
</FxTable>
</template>
<script setup lang="ts">
import { FxTable, FxTableColumn } from '@fx/components'
const indexMethod = (index: number) => index * 2
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Home',
},
{
date: '2016-05-02',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Office',
},
{
date: '2016-05-04',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Home',
},
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Office',
},
]
</script>1
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
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
行/列合并
span-method 合并单元格,返回 [rowspan, colspan](数组)或 { rowspan, colspan }(对象),返回 0 表示该单元格被合并。
vue
<template>
<div>
<FxTable
:data="tableData"
:span-method="arraySpanMethod"
border
style="width: 100%"
>
<FxTableColumn prop="id" label="ID" width="180" />
<FxTableColumn prop="name" label="Name" />
<FxTableColumn prop="amount1" sortable label="Amount 1" />
<FxTableColumn prop="amount2" sortable label="Amount 2" />
<FxTableColumn prop="amount3" sortable label="Amount 3" />
</FxTable>
<FxTable
:data="tableData"
:span-method="objectSpanMethod"
border
style="width: 100%; margin-top: 20px"
>
<FxTableColumn prop="id" label="ID" width="180" />
<FxTableColumn prop="name" label="Name" />
<FxTableColumn prop="amount1" label="Amount 1" />
<FxTableColumn prop="amount2" label="Amount 2" />
<FxTableColumn prop="amount3" label="Amount 3" />
</FxTable>
</div>
</template>
<script lang="ts" setup>
import type { TableColumnCtx } from '@fx/components'
import { FxTable, FxTableColumn } from '@fx/components'
interface User {
id: string
name: string
amount1: string
amount2: string
amount3: number
}
interface SpanMethodProps {
row: User
column: TableColumnCtx<User>
rowIndex: number
columnIndex: number
}
// 数组形式:返回 [rowspan, colspan]
const arraySpanMethod = ({ rowIndex, columnIndex }: SpanMethodProps) => {
if (rowIndex % 2 === 0) {
if (columnIndex === 0) {
return [1, 2]
} else if (columnIndex === 1) {
return [0, 0]
}
}
}
// 对象形式:返回 { rowspan, colspan }
const objectSpanMethod = ({ rowIndex, columnIndex }: SpanMethodProps) => {
if (columnIndex === 0) {
if (rowIndex % 2 === 0) {
return {
rowspan: 2,
colspan: 1,
}
} else {
return {
rowspan: 0,
colspan: 0,
}
}
}
}
const tableData: User[] = [
{ id: '12987122', name: 'Tom', amount1: '234', amount2: '3.2', amount3: 10 },
{ id: '12987123', name: 'Tom', amount1: '165', amount2: '4.43', amount3: 12 },
{ id: '12987124', name: 'Tom', amount1: '324', amount2: '1.9', amount3: 9 },
{ id: '12987125', name: 'Tom', amount1: '621', amount2: '2.2', amount3: 17 },
{ id: '12987126', name: 'Tom', amount1: '539', amount2: '4.1', amount3: 15 },
]
</script>1
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
83
84
85
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
83
84
85
固定列
fixed 设为 true 或 'left' 固定在左侧,'right' 固定在右侧。
vue
<template>
<FxTable :data="tableData" style="width: 100%">
<FxTableColumn fixed prop="date" label="Date" width="150" />
<FxTableColumn prop="name" label="Name" width="120" />
<FxTableColumn prop="state" label="State" width="120" />
<FxTableColumn prop="city" label="City" width="120" />
<FxTableColumn prop="address" label="Address" width="600" />
<FxTableColumn prop="zip" label="Zip" width="120" />
<FxTableColumn fixed="right" label="Operations" min-width="120">
<template #default>
<FxBtn link type="primary" size="small" @click="handleClick">
Detail
</FxBtn>
<FxBtn link type="primary" size="small">Edit</FxBtn>
</template>
</FxTableColumn>
</FxTable>
</template>
<script lang="ts" setup>
import { FxTable, FxTableColumn, FxBtn } from '@fx/components'
const handleClick = () => {
// 详情操作
}
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-02',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-04',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
]
</script>1
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
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
固定表头
height 或 max-height 限定高度后,表头固定、表体滚动。
vue
<template>
<FxTable :data="tableData" height="250" style="width: 100%">
<FxTableColumn prop="date" label="Date" width="180" />
<FxTableColumn prop="name" label="Name" width="180" />
<FxTableColumn prop="address" label="Address" />
</FxTable>
</template>
<script lang="ts" setup>
import { FxTable, FxTableColumn } from '@fx/components'
const tableData = [
{ date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-08', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-06', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
{ date: '2016-05-07', name: 'Tom', address: 'No. 189, Grove St, Los Angeles' },
]
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
固定列 + 固定表头
vue
<template>
<FxTable :data="tableData" style="width: 100%" height="250">
<FxTableColumn fixed prop="date" label="Date" width="150" />
<FxTableColumn prop="name" label="Name" width="120" />
<FxTableColumn prop="state" label="State" width="120" />
<FxTableColumn prop="city" label="City" width="320" />
<FxTableColumn prop="address" label="Address" width="600" />
<FxTableColumn prop="zip" label="Zip" />
</FxTable>
</template>
<script lang="ts" setup>
import { FxTable, FxTableColumn } from '@fx/components'
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-02',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-04',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-08',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-06',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-07',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
]
</script>1
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
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
合计行
show-summary 显示合计行,默认对数值列求和(首列显示 sum-text),summary-method 自定义合计逻辑。
vue
<template>
<FxTable :data="tableData" border show-summary style="width: 100%">
<FxTableColumn prop="id" label="ID" width="180" />
<FxTableColumn prop="name" label="Name" />
<FxTableColumn prop="amount1" sortable label="Amount 1" />
<FxTableColumn prop="amount2" sortable label="Amount 2" />
<FxTableColumn prop="amount3" sortable label="Amount 3" />
</FxTable>
<FxTable
:data="tableData"
border
height="200"
:summary-method="getSummaries"
show-summary
style="width: 100%; margin-top: 20px"
>
<FxTableColumn prop="id" label="ID" width="180" />
<FxTableColumn prop="name" label="Name" />
<FxTableColumn prop="amount1" label="Cost 1 ($)" />
<FxTableColumn prop="amount2" label="Cost 2 ($)" />
<FxTableColumn prop="amount3" label="Cost 3 ($)" />
</FxTable>
</template>
<script lang="ts" setup>
import { h } from 'vue'
import type { VNode } from 'vue'
import type { TableColumnCtx } from '@fx/components'
import { FxTable, FxTableColumn } from '@fx/components'
interface Product {
id: string
name: string
amount1: string
amount2: string
amount3: number
}
interface SummaryMethodProps<T extends Product = Product> {
columns: TableColumnCtx<T>[]
data: T[]
}
const getSummaries = (param: SummaryMethodProps) => {
const { columns, data } = param
const sums: (string | VNode)[] = []
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = h('div', { style: { textDecoration: 'underline' } }, [
'Total Cost',
])
return
}
const values = data.map((item) => Number(item[column.property]))
if (!values.every((value) => Number.isNaN(value))) {
sums[index] = `$ ${values.reduce((prev: number, curr: number) => {
const value = Number(curr)
if (!Number.isNaN(value)) {
return prev + curr
}
return prev
}, 0)}`
} else {
sums[index] = 'N/A'
}
})
return sums
}
const tableData: Product[] = [
{ id: '12987122', name: 'Tom', amount1: '234', amount2: '3.2', amount3: 10 },
{ id: '12987123', name: 'Tom', amount1: '165', amount2: '4.43', amount3: 12 },
{ id: '12987124', name: 'Tom', amount1: '324', amount2: '1.9', amount3: 9 },
{ id: '12987125', name: 'Tom', amount1: '621', amount2: '2.2', amount3: 17 },
{ id: '12987126', name: 'Tom', amount1: '539', amount2: '4.1', amount3: 15 },
]
</script>1
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
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
展开行
type="expand" 列配合 #default 插槽渲染展开内容。
vue
<template>
<div style="margin-bottom: 12px">
switch parent border: <FxSwitch v-model="parentBorder" /> switch child
border: <FxSwitch v-model="childBorder" /> preserve expanded:
<FxSwitch v-model="preserveExpanded" />
</div>
<FxTable
:data="tableData"
:border="parentBorder"
:preserve-expanded-content="preserveExpanded"
style="width: 100%"
>
<FxTableColumn type="expand">
<template #default="props">
<div style="margin: 16px">
<p style="margin: 0 0 8px">State: {{ props.row.state }}</p>
<p style="margin: 0 0 8px">City: {{ props.row.city }}</p>
<p style="margin: 0 0 8px">Address: {{ props.row.address }}</p>
<p style="margin: 0 0 8px">Zip: {{ props.row.zip }}</p>
<h3>Family</h3>
<FxTable :data="props.row.family" :border="childBorder">
<FxTableColumn label="Name" prop="name" />
<FxTableColumn label="State" prop="state" />
<FxTableColumn label="City" prop="city" />
<FxTableColumn label="Address" prop="address" />
<FxTableColumn label="Zip" prop="zip" />
</FxTable>
</div>
</template>
</FxTableColumn>
<FxTableColumn label="Date" prop="date" />
<FxTableColumn label="Name" prop="name" />
</FxTable>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { FxTable, FxTableColumn, FxSwitch } from '@fx/components'
interface FamilyMember {
name: string
state: string
city: string
address: string
zip: string
}
interface Row extends FamilyMember {
date: string
family: FamilyMember[]
}
const parentBorder = ref(false)
const childBorder = ref(false)
const preserveExpanded = ref(false)
const makeFamily = (): FamilyMember[] => [
{
name: 'Jerry',
state: 'California',
city: 'San Francisco',
address: '3650 21st St, San Francisco',
zip: 'CA 94114',
},
{
name: 'Spike',
state: 'California',
city: 'San Francisco',
address: '3650 21st St, San Francisco',
zip: 'CA 94114',
},
{
name: 'Tyke',
state: 'California',
city: 'San Francisco',
address: '3650 21st St, San Francisco',
zip: 'CA 94114',
},
]
const tableData: Row[] = [
{
date: '2016-05-03',
name: 'Tom',
state: 'California',
city: 'San Francisco',
address: '3650 21st St, San Francisco',
zip: 'CA 94114',
family: makeFamily(),
},
{
date: '2016-05-02',
name: 'Tom',
state: 'California',
city: 'San Francisco',
address: '3650 21st St, San Francisco',
zip: 'CA 94114',
family: makeFamily(),
},
{
date: '2016-05-04',
name: 'Tom',
state: 'California',
city: 'San Francisco',
address: '3650 21st St, San Francisco',
zip: 'CA 94114',
family: makeFamily(),
},
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'San Francisco',
address: '3650 21st St, San Francisco',
zip: 'CA 94114',
family: makeFamily(),
},
{
date: '2016-05-08',
name: 'Tom',
state: 'California',
city: 'San Francisco',
address: '3650 21st St, San Francisco',
zip: 'CA 94114',
family: makeFamily(),
},
{
date: '2016-05-06',
name: 'Tom',
state: 'California',
city: 'San Francisco',
address: '3650 21st St, San Francisco',
zip: 'CA 94114',
family: makeFamily(),
},
{
date: '2016-05-07',
name: 'Tom',
state: 'California',
city: 'San Francisco',
address: '3650 21st St, San Francisco',
zip: 'CA 94114',
family: makeFamily(),
},
]
</script>1
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
分组表头
FxTableColumn 嵌套即可生成多级表头。
vue
<template>
<FxTable :data="tableData" style="width: 100%">
<FxTableColumn prop="date" label="Date" width="150" />
<FxTableColumn label="Delivery Info">
<FxTableColumn prop="name" label="Name" width="120" />
<FxTableColumn label="Address Info">
<FxTableColumn prop="state" label="State" width="120" />
<FxTableColumn prop="city" label="City" width="120" />
<FxTableColumn prop="address" label="Address" />
<FxTableColumn prop="zip" label="Zip" width="120" />
</FxTableColumn>
</FxTableColumn>
</FxTable>
</template>
<script lang="ts" setup>
import { FxTable, FxTableColumn } from '@fx/components'
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-02',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-04',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-08',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-06',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-07',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
]
</script>1
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
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
树形数据 / 懒加载
row-key 必填;tree-props 配置子节点字段,子节点写在 children 即可渲染为树形;lazy + load 实现懒加载(节点需标 hasChildren: true)。
vue
<template>
<div>
<FxTable
:data="tableData"
style="width: 100%; margin-bottom: 20px"
row-key="id"
border
default-expand-all
>
<FxTableColumn prop="date" label="Date" sortable />
<FxTableColumn prop="name" label="Name" sortable />
<FxTableColumn prop="address" label="Address" sortable />
</FxTable>
<FxTable
:data="tableData1"
style="width: 100%"
row-key="id"
border
lazy
:load="load"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<FxTableColumn prop="date" label="Date" />
<FxTableColumn prop="name" label="Name" />
<FxTableColumn prop="address" label="Address" />
</FxTable>
</div>
</template>
<script lang="ts" setup>
import type { TreeNode } from '@fx/components'
import { FxTable, FxTableColumn } from '@fx/components'
interface User {
id: number
date: string
name: string
address: string
hasChildren?: boolean
children?: User[]
}
const load = (
_row: User,
_treeNode: TreeNode,
resolve: (data: User[]) => void,
) => {
setTimeout(() => {
resolve([
{
id: 31,
date: '2016-05-01',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 32,
date: '2016-05-01',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
])
}, 1000)
}
const tableData: User[] = [
{
id: 1,
date: '2016-05-02',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 2,
date: '2016-05-04',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 3,
date: '2016-05-01',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
children: [
{
id: 31,
date: '2016-05-01',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 32,
date: '2016-05-01',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
],
},
{
id: 4,
date: '2016-05-03',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
]
const tableData1: User[] = [
{
id: 1,
date: '2016-05-02',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 2,
date: '2016-05-04',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 3,
date: '2016-05-01',
name: 'wangxiaohu',
hasChildren: true,
address: 'No. 189, Grove St, Los Angeles',
},
{
id: 4,
date: '2016-05-03',
name: 'wangxiaohu',
address: 'No. 189, Grove St, Los Angeles',
},
]
</script>1
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
行状态高亮
通过 row-class-name 为行添加状态 class(如 warning-row / success-row),结合 CSS 变量 --fx-table-tr-bg-color 自定义行背景色。
vue
<template>
<FxTable
:data="tableData"
style="width: 100%"
:row-class-name="tableRowClassName"
>
<FxTableColumn prop="date" label="Date" width="180" />
<FxTableColumn prop="name" label="Name" width="180" />
<FxTableColumn prop="address" label="Address" />
</FxTable>
</template>
<script setup lang="ts">
import { FxTable, FxTableColumn } from '@fx/components'
const tableRowClassName = ({
rowIndex,
}: {
row: Record<string, unknown>
rowIndex: number
}) => {
if (rowIndex === 1) return 'warning-row'
if (rowIndex === 3) return 'success-row'
return ''
}
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]
</script>
<style>
.fx-table .warning-row {
--fx-table-tr-bg-color: var(--fx-color-warning-light-9);
}
.fx-table .success-row {
--fx-table-tr-bg-color: var(--fx-color-success-light-9);
}
</style>1
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
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
固定列 + 分组表头
固定列与分组表头组合使用:左固定列、嵌套分组表头、右固定列共存。
vue
<template>
<FxTable :data="tableData" style="width: 100%" height="250">
<FxTableColumn prop="date" label="Date" />
<FxTableColumn prop="name" label="Name" />
<FxTableColumn prop="zip" label="Zip" />
<FxTableColumn label="Address Info" fixed="right">
<FxTableColumn prop="state" label="State" />
<FxTableColumn prop="city" label="City" />
<FxTableColumn prop="address" label="Address" min-width="200" />
</FxTableColumn>
</FxTable>
</template>
<script lang="ts" setup>
import { FxTable, FxTableColumn } from '@fx/components'
interface Row {
date: string
name: string
state: string
city: string
address: string
zip: string
}
const tableData: Row[] = [
{
date: '2016-05-03',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-02',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-04',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-08',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-06',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-07',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
]
</script>1
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
83
84
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
83
84
固定表头 + 流体高度
max-height 限制表体最大高度,内容超出时表体滚动且表头固定。
vue
<template>
<FxTable :data="tableData" style="width: 100%" max-height="250">
<FxTableColumn fixed prop="date" label="Date" width="150" />
<FxTableColumn prop="name" label="Name" width="120" />
<FxTableColumn prop="state" label="State" width="120" />
<FxTableColumn prop="city" label="City" width="120" />
<FxTableColumn prop="address" label="Address" width="600" />
<FxTableColumn prop="zip" label="Zip" width="120" />
<FxTableColumn fixed="right" label="Operations" min-width="120">
<template #default="scope">
<FxBtn
link
type="primary"
size="small"
@click.prevent="deleteRow(scope.$index)"
>
Remove
</FxBtn>
</template>
</FxTableColumn>
</FxTable>
<FxBtn style="margin-top: 16px; width: 100%" @click="onAddItem">
Add Item
</FxBtn>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { FxTable, FxTableColumn, FxBtn } from '@fx/components'
interface Row {
date: string
name: string
state: string
city: string
address: string
zip: string
}
const now = new Date()
// 原生日期格式化(YYYY-MM-DD),避免引入 dayjs 依赖
const formatDate = (d: Date) => {
const y = d.getFullYear()
const m = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
return `${y}-${m}-${day}`
}
const tableData = ref<Row[]>([
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-02',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-03',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
])
const deleteRow = (index: number) => {
tableData.value.splice(index, 1)
}
const onAddItem = () => {
now.setDate(now.getDate() + 1)
tableData.value.push({
date: formatDate(now),
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
})
}
</script>1
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
83
84
85
86
87
88
89
90
91
92
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
83
84
85
86
87
88
89
90
91
92
Table API
FxTable Attributes
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| data | 表格数据 | array | [] |
| size | 尺寸 | 'large' | 'default' | 'small' | 'default' |
| height | 表格高度 | string | number | — |
| max-height | 表格最大高度 | string | number | — |
| fit | 列宽是否自适应容器 | boolean | true |
| stripe | 是否显示斑马纹 | boolean | false |
| border | 是否显示纵向边框 | boolean | false |
| row-key | 行数据的 Key | string | ((row) => string) | — |
| show-header | 是否显示表头 | boolean | true |
| table-layout | 布局算法 | 'fixed' | 'auto' | 'fixed' |
| row-class-name | 行的 className | string | (({ row, rowIndex }) => string) | — |
| row-style | 行样式 | object | (({ row, rowIndex }) => object) | — |
| cell-class-name | 单元格 className | string | (({ row, rowIndex, column, columnIndex }) => string) | — |
| cell-style | 单元格样式 | object | (({ row, rowIndex, column, columnIndex }) => object) | — |
| header-row-class-name | 表头行 className | string | fn | — |
| header-row-style | 表头行样式 | object | fn | — |
| header-cell-class-name | 表头单元格 className | string | fn | — |
| header-cell-style | 表头单元格样式 | object | fn | — |
| empty-text | 空数据文案 | string | '暂无数据' |
| highlight-current-row | 单选高亮当前行 | boolean | false |
| current-row-key | 当前行的 key(需配合 row-key) | string | number | — |
| default-sort | 默认排序列 | { prop: string, order: 'ascending' | 'descending' } | — |
| select-on-indeterminate | 半选时点击全选的行为 | boolean | true |
| tooltip-effect | 溢出 tooltip 主题 | 'dark' | 'light' | 'dark' |
| tooltip-options | 溢出 tooltip 选项透传 | object | — |
| show-overflow-tooltip | 单元格溢出全局提示 | boolean | false |
| append-filter-panel-to | 筛选面板 teleport 目标 | string | — |
| span-method | 合并单元格方法 | ({ row, column, rowIndex, columnIndex }) => [number, number] | { rowspan, colspan } | — |
| show-summary | 是否显示合计行 | boolean | false |
| sum-text | 合计行首列文案 | string | '合计' |
| summary-method | 自定义合计方法 | ({ columns, data }) => array | — |
| default-expand-all | 默认展开所有行 | boolean | false |
| expand-row-keys | 展开行的 keys(需配合 row-key) | array | — |
| lazy | 树形懒加载 | boolean | false |
| load | 懒加载回调(lazy 时) | (row, treeNode, resolve) => void | — |
| indent | 树形缩进(px) | number | 16 |
| tree-props | 树形配置 | { hasChildren?, children?, checkStrictly? } | { children: 'children', hasChildren: 'hasChildren', checkStrictly: false } |
| native-scrollbar | 启用原生滚动条(不走 FxScrollbar) | boolean | false |
| scrollbar-always-on | 滚动条常显 | boolean | false |
| scrollbar-tabindex | 滚动条 tabindex | number | — |
| row-expandable | 行是否可展开(type="expand") | (row, index) => boolean | — |
| flexible | flex 容器下保证 min-size 不被撑大 | boolean | false |
| allow-drag-last-column | 允许拖拽最后一列列宽 | boolean | true |
| preserve-expanded-content | 展开行收起后保留 DOM | boolean | false |
FxTable Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| cell-click | 单元格点击 | (row, column, cell, event) |
| cell-dblclick | 单元格双击 | (row, column, cell, event) |
| cell-mouse-enter | 单元格移入 | (row, column, cell, event) |
| cell-mouse-leave | 单元格移出 | (row, column, cell, event) |
| cell-contextmenu | 单元格右键 | (row, column, cell, event) |
| row-click | 行点击 | (row, column, event) |
| row-dblclick | 行双击 | (row, column, event) |
| row-contextmenu | 行右键 | (row, column, event) |
| header-click | 表头点击 | (column, event) |
| header-contextmenu | 表头右键 | (column, event) |
| scroll | 滚动 | ({ scrollLeft, scrollTop }) |
| select | 手动勾选行时 | (selection, row) |
| select-all | 点击全选时 | (selection) |
| selection-change | 选中项变化 | (selection) |
| sort-change | 排序变化 | ({ column, prop, order }) |
| filter-change | 筛选变化 | (filters) |
| current-change | 当前行变化 | (currentRow, oldCurrentRow) |
| expand-change | 行展开(数组)或树形节点展开(boolean) | (row, expandedRows | expanded) |
| header-dragend | 列宽拖拽结束后触发 | (newWidth, oldWidth, column, event) |
FxTable Slots
| 名称 | 说明 |
|---|---|
| default | 放 FxTableColumn |
| empty | 空数据自定义内容 |
| append | 表体底部追加内容 |
FxTable Exposes
| 名称 | 说明 | 参数 |
|---|---|---|
| doLayout | 重新计算布局 | — |
| scrollTo | 滚动到指定坐标 | (x, y) |
| setScrollLeft | 设置横向滚动位置 | (left) |
| setScrollTop | 设置纵向滚动位置 | (top) |
| sort | 程序化排序 | (prop, order) |
| clearSort | 清除排序 | — |
| clearFilter | 清除筛选 | (columnKeys?) |
| setCurrentRow | 设置当前行(不传参数则清空) | (row?) |
| getSelectionRows | 获取选中行数组 | — |
| getHalfSelectionRows | 获取半选行数组(树形 indeterminate) | — |
| toggleRowSelection | 切换行选中(第 3 参 ignoreSelectable 绕过 selectable) | (row, selected?, ignoreSelectable?) |
| clearSelection | 清除选中 | — |
| toggleAllSelection | 切换全选 | — |
| toggleRowExpansion | 切换行展开 | (row, expanded?) |
| toggleTreeExpansion | 切换树形节点展开(需 row-key) | (row, expanded?) |
| updateKeyChildren | 更新懒加载子节点(需 lazy + row-key) | (key, data) |
FxTableColumn Attributes
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| type | 列类型:default / selection / index / expand | string | 'default' |
| label | 列标题 | string | — |
| prop | 字段名(别名 property) | string | — |
| width | 列宽 | string | number | — |
| min-width | 最小列宽(按比例分配剩余) | string | number | — |
| align | 排列方向 | 'left' | 'center' | 'right' | — |
| header-align | 表头排列方向 | 'left' | 'center' | 'right' | 同 align |
| class-name | 列单元格 className | string | — |
| label-class-name | 列标题 className | string | — |
| formatter | 单元格格式化函数 | (row, column, cellValue, index) => VNode | string | — |
| column-key | 列标识(筛选 / 选择定位用) | string | — |
| index | 自定义序号(type="index" 用) | number | ((index) => number) | — |
| sortable | 是否可排序('custom' 表示远程排序,需自行监听 sort-change) | boolean | 'custom' | false |
| sort-method | 自定义排序比较函数 | (a, b) => number | — |
| sort-by | 排序依据字段 | string | string[] | ((row) => string) | — |
| sort-orders | 排序切换顺序 | ('ascending' | 'descending' | null)[] | ['ascending', 'descending', null] |
| resizable | 列宽可拖拽(阶段③) | boolean | true |
| filters | 筛选项数组 | { text, value }[] | — |
| filter-method | 筛选过滤函数 | (value, row, column) => boolean | — |
| filter-multiple | 多选筛选 | boolean | true |
| filter-placement | 筛选面板位置 | Placement | 'bottom-start' |
| filtered-value | 受控筛选值 | string[] | — |
| selectable | 行是否可选(type="selection") | (row, index) => boolean | — |
| reserve-selection | 数据变化时保留选中(需配合 row-key) | boolean | false |
| show-overflow-tooltip | 单元格溢出提示(可传对象透传 tooltip 选项) | boolean | object | — |
| tooltip-formatter | 溢出 tooltip 内容格式化 | ({ row, column, cellValue }) => VNode | string | — |
| fixed | 固定列 | boolean | 'left' | 'right' | — |
FxTableColumn Slots
| 名称 | 说明 | 参数 |
|---|---|---|
| default | 自定义单元格内容(type="expand" 时为展开行内容) | { row, column, $index } |
| header | 自定义表头内容 | { column, $index } |
| expand | 自定义展开触发图标内容(type="expand") | { expanded, expandable } |
| filter-icon | 自定义筛选图标内容 | { filterOpened } |
