Skip to content

Commit 0c09170

Browse files
authored
feat(Table): 丰富自定义列参数&新增支持自定义表头 (DevCloudFE#397)
1 parent de1acca commit 0c09170

File tree

4 files changed

+223
-32
lines changed

4 files changed

+223
-32
lines changed

packages/devui-vue/devui/table/src/components/column/column-types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { DefaultRow } from '../../table-types';
33
import { TableStore } from '../../store/store-types';
44

55
// eslint-disable-next-line no-use-before-define
6-
export type Formatter = (row: DefaultRow, column: Column, cellValue: any, rowIndex: number) => VNode[];
6+
export type Formatter = (row: DefaultRow, column: Column, cellValue: any, rowIndex: number) => VNode;
77

88
export type CompareFn<T = any> = (field: string, a: T, b: T) => boolean;
99

packages/devui-vue/devui/table/src/components/column/config.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,16 @@ export const cellMap = {
3333
return rowIndex + 1;
3434
},
3535
},
36+
default: {
37+
renderHeader(column: Column): VNode {
38+
return h('span', { class: 'title' }, column.header ?? '');
39+
},
40+
renderCell(rowData: DefaultRow, column: Column, store: TableStore, rowIndex: number): VNode {
41+
const value = column.field ? rowData[column.field] : '';
42+
if (column.formatter) {
43+
return column.formatter(rowData, column, value, rowIndex);
44+
}
45+
return value?.toString?.() ?? '';
46+
},
47+
},
3648
};

packages/devui-vue/devui/table/src/components/column/use-column.ts

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { TableStore } from '../../store/store-types';
66
import { formatWidth, formatMinWidth } from '../../utils';
77
import { cellMap } from './config';
88

9-
export function createColumn(props: ToRefs<TableColumnProps>, templates: Slots): Column {
9+
export function createColumn(props: ToRefs<TableColumnProps>, slots: Slots): Column {
1010
const {
1111
type,
1212
field,
@@ -26,20 +26,18 @@ export function createColumn(props: ToRefs<TableColumnProps>, templates: Slots):
2626
const column: Column = reactive({});
2727
column.type = type.value;
2828

29-
function defaultRenderHeader(columnItem: Column) {
30-
return h('span', { class: 'title' }, columnItem.header ?? '');
29+
function renderHeader(columnItem: Column, store: TableStore) {
30+
if (slots.header) {
31+
return slots.header(columnItem);
32+
}
33+
return cellMap[type.value || 'default'].renderHeader(columnItem, store);
3134
}
3235

33-
function defaultRenderCell(rowData: DefaultRow, columnItem: Column, store: TableStore, rowIndex: number) {
34-
const value = columnItem.field ? rowData[columnItem.field] : '';
35-
if (templates.default) {
36-
return templates.default(rowData);
37-
}
38-
if (columnItem.formatter) {
39-
return columnItem.formatter(rowData, columnItem, value, rowIndex);
36+
function renderCell(rowData: DefaultRow, columnItem: Column, store: TableStore, rowIndex: number) {
37+
if (slots.default) {
38+
return slots.default({ row: rowData, rowIndex });
4039
}
41-
42-
return value?.toString?.() ?? '';
40+
return cellMap[type.value || 'default'].renderCell(rowData, columnItem, store, rowIndex);
4341
}
4442

4543
watch(
@@ -88,11 +86,11 @@ export function createColumn(props: ToRefs<TableColumnProps>, templates: Slots):
8886

8987
// 基础渲染功能
9088
onBeforeMount(() => {
91-
column.renderHeader = type.value ? cellMap[type.value].renderHeader : defaultRenderHeader;
92-
column.renderCell = type.value ? cellMap[type.value].renderCell : defaultRenderCell;
89+
column.renderHeader = renderHeader;
90+
column.renderCell = renderCell;
9391
column.formatter = formatter?.value;
94-
column.customFilterTemplate = templates.customFilterTemplate;
95-
column.subColumns = templates.subColumns;
92+
column.customFilterTemplate = slots.customFilterTemplate;
93+
column.subColumns = slots.subColumns;
9694
});
9795

9896
return column;

packages/devui-vue/docs/components/table/index.md

Lines changed: 196 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,22 @@
22

33
展示行列数据。
44

5-
### 何时使用
5+
#### 何时使用
66

77
1. 当有大量结构化的数据需要展现时;
88
2. 当需要对数据进行排序、过滤、自定义操作等复杂行为时。
99

1010
### 基本用法
1111

12-
:::demo 简单表格,`d-table`组件上的`data`属性传入要展示的数据,`d-table-column`组件上通过`field`传入对应列内容的字段名,`header`传入对应列的标题。
12+
:::demo 简单表格,`d-table`组件上的`data`属性传入要展示的数据,`d-column`组件上通过`field`传入对应列内容的字段名,`header`传入对应列的标题。
1313

1414
```vue
1515
<template>
1616
<d-table :data="baseTableData">
17-
<d-column type="index"></d-column>
1817
<d-column field="firstName" header="First Name"></d-column>
1918
<d-column field="lastName" header="Last Name"></d-column>
2019
<d-column field="gender" header="Gender"></d-column>
2120
<d-column field="date" header="Date of birth"></d-column>
22-
<d-column header="Operation">
23-
<template #default="scope">
24-
<d-button @click="handleClick(scope)">编辑</d-button>
25-
</template>
26-
</d-column>
2721
</d-table>
2822
</template>
2923
@@ -58,11 +52,8 @@ export default defineComponent({
5852
date: '1990/01/14',
5953
},
6054
]);
61-
const handleClick = (scope) => {
62-
console.log(scope);
63-
};
6455
65-
return { baseTableData, handleClick };
56+
return { baseTableData };
6657
},
6758
});
6859
</script>
@@ -278,6 +269,195 @@ export default defineComponent({
278269

279270
:::
280271

272+
### 索引列
273+
274+
:::demo 通过添加一个`d-column`并且设置`type`参数为`index`即可给表格添加索引。索引列的表头默认展示`#`,可通过`header`参数传入指定内容。
275+
276+
```vue
277+
<template>
278+
<div>
279+
<d-table :data="data">
280+
<d-column type="index"></d-column>
281+
<d-column field="firstName" header="First Name"></d-column>
282+
<d-column field="lastName" header="Last Name"></d-column>
283+
<d-column field="gender" header="Gender"></d-column>
284+
<d-column field="date" header="Date of birth"></d-column>
285+
</d-table>
286+
</div>
287+
</template>
288+
289+
<script>
290+
import { defineComponent, ref } from 'vue';
291+
292+
export default defineComponent({
293+
setup() {
294+
const data = ref([
295+
{
296+
firstName: 'po',
297+
lastName: 'Lang',
298+
gender: 'Male',
299+
date: '1990/01/15',
300+
},
301+
{
302+
firstName: 'john',
303+
lastName: 'Li',
304+
gender: 'Female',
305+
date: '1990/01/16',
306+
},
307+
{
308+
firstName: 'peng',
309+
lastName: 'Li',
310+
gender: 'Male',
311+
date: '1990/01/17',
312+
},
313+
{
314+
firstName: 'Dale',
315+
lastName: 'Yu',
316+
gender: 'Female',
317+
date: '1990/01/18',
318+
},
319+
]);
320+
321+
return { data };
322+
},
323+
});
324+
</script>
325+
```
326+
327+
:::
328+
329+
### 自定义列
330+
331+
:::demo 通过`d-column`子组件提供的`default`插槽可以实现自定义列,插槽提供`row``rowIndex`两个参数,分别代表行数据和行索引值。
332+
333+
```vue
334+
<template>
335+
<d-table :data="dataSource">
336+
<d-column type="index">
337+
<template #default="scope">
338+
{{ `No.${scope.rowIndex + 1}` }}
339+
</template>
340+
</d-column>
341+
<d-column field="firstName" header="First Name"></d-column>
342+
<d-column field="lastName" header="Last Name"></d-column>
343+
<d-column field="gender" header="Gender"></d-column>
344+
<d-column field="date" header="Date of birth"></d-column>
345+
<d-column header="Operation">
346+
<template #default="scope">
347+
<d-button @click="handleClick(scope.row)">编辑</d-button>
348+
</template>
349+
</d-column>
350+
</d-table>
351+
</template>
352+
353+
<script>
354+
import { defineComponent, ref } from 'vue';
355+
356+
export default defineComponent({
357+
setup() {
358+
const dataSource = ref([
359+
{
360+
firstName: 'Mark',
361+
lastName: 'Otto',
362+
date: '1990/01/11',
363+
gender: 'Male',
364+
},
365+
{
366+
firstName: 'Jacob',
367+
lastName: 'Thornton',
368+
gender: 'Female',
369+
date: '1990/01/12',
370+
},
371+
{
372+
firstName: 'Danni',
373+
lastName: 'Chen',
374+
gender: 'Male',
375+
date: '1990/01/13',
376+
},
377+
{
378+
firstName: 'green',
379+
lastName: 'gerong',
380+
gender: 'Male',
381+
date: '1990/01/14',
382+
},
383+
]);
384+
const handleClick = (row) => {
385+
console.log(row);
386+
};
387+
388+
return { dataSource, handleClick };
389+
},
390+
});
391+
</script>
392+
```
393+
394+
:::
395+
396+
### 自定义表头
397+
398+
:::demo 通过`d-column`子组件提供的`header`插槽可以实现自定义表头。
399+
400+
```vue
401+
<template>
402+
<d-table :data="dataSource">
403+
<d-column field="firstName">
404+
<template #header>
405+
<div>
406+
<span style="margin-right:4px;">First Name</span>
407+
<d-popover content="some tips text" trigger="hover" :position="['top']">
408+
<template #reference>
409+
<d-icon name="info-o"></d-icon>
410+
</template>
411+
</d-popover>
412+
</div>
413+
</template>
414+
</d-column>
415+
<d-column field="lastName" header="Last Name"></d-column>
416+
<d-column field="gender" header="Gender"></d-column>
417+
<d-column field="date" header="Date of birth"></d-column>
418+
</d-table>
419+
</template>
420+
421+
<script>
422+
import { defineComponent, ref } from 'vue';
423+
424+
export default defineComponent({
425+
setup() {
426+
const dataSource = ref([
427+
{
428+
firstName: 'Mark',
429+
lastName: 'Otto',
430+
date: '1990/01/11',
431+
gender: 'Male',
432+
},
433+
{
434+
firstName: 'Jacob',
435+
lastName: 'Thornton',
436+
gender: 'Female',
437+
date: '1990/01/12',
438+
},
439+
{
440+
firstName: 'Danni',
441+
lastName: 'Chen',
442+
gender: 'Male',
443+
date: '1990/01/13',
444+
},
445+
{
446+
firstName: 'green',
447+
lastName: 'gerong',
448+
gender: 'Male',
449+
date: '1990/01/14',
450+
},
451+
]);
452+
453+
return { dataSource };
454+
},
455+
});
456+
</script>
457+
```
458+
459+
:::
460+
281461
### 空数据模板
282462

283463
:::demo 当传入的数据为空时,默认展示空数据模板。
@@ -586,9 +766,10 @@ export default defineComponent({
586766

587767
### d-column 插槽
588768

589-
| 插槽名 | 说明 |
590-
| :------ | :--------------------- |
591-
| default | 默认插槽,自定义列内容 |
769+
| 插槽名 | 说明 |
770+
| :------ | :----------------------- |
771+
| default | 默认插槽,自定义列内容 |
772+
| header | 表头插槽,自定义表头内容 |
592773

593774
### 类型定义
594775

0 commit comments

Comments
 (0)