UI 框架-Table 组件

自定义表格也是非常香的


需求分析

惯例先行需求分析

  1. 基于原生 table 标签的强语义
  2. 允许用户自定义表头、表体
  3. 可选是否具有边框

那么可以整理出以下参数表格

参数 含义 类型 可选值 默认值
heads 表头 Array 数组,每一项包含两个 string 字段:name、identifier 必填
datas 表数据 Array 数组,每一项包含与 heads 相同数量的 string 字段 必填
bordered 是否有边框 boolean false / true false

骨架

容易得到如下骨架

1
2
3
4
5
<template>
<table class="laby-table" :bordered="bordered">
<slot></slot>
</table>
</template>

让用户自己填写内容即可

功能

先 ts 声明

1
2
3
declare const props: {
bordered: boolean;
};

然后在 export default 中,写入我们的参数

1
2
3
4
5
6
7
8
9
export default {
name: "LabyTable",
props: {
bordered: {
type: Boolean,
default: false,
},
},
};

样式表

然后补全样式表

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
.laby-table {
width: 100%;
text-align: left;
border-spacing: 0;
th,
td {
padding: 12px;
}
tbody {
> tr {
transition: background-color 250ms;
&:nth-child(even) {
background: rgb(247, 247, 247);
}
&:hover {
background: #ffeaf4;
}
}
}
}
.laby-table[bordered="true"] {
border: 1px solid rgb(235, 235, 235);
tr,
th,
td {
border: 1px solid rgb(235, 235, 235);
}
}

注意,当设置属性 bordered 的时候,因为它不是 DOM 元素本有的属性,所以无论什么情况都会被添加,只不过值可能是 false

但是 disabled 属性就没有这个问题,它为 false 值时不会绑定到 DOM 元素上

所以,此处属性选择器要写 [bordered="true"]

测试

引入文档页看一下

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
// src/components/Dialog.vue
<template>
<div>Table 文档</div>
<laby-table bordered>
<thead>
<tr>
<th v-for="(head, index) in heads" :key="index">{{ head.name }}</th>
<th>其余操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(data, index) in datas" :key="index">
<td v-for="key in keys" :key="key" v-html="data[key]"></td>
<td>
<laby-button @click="del(index)">删除</laby-button>
</td>
</tr>
</tbody>
</laby-table>
</template>
<script lang="ts">
import LabyButton from "../lib/Button.vue";
import LabyTable from "../lib/Table.vue";
import { ref } from "vue";
export default {
components: {
LabyTable,
LabyButton,
},
setup() {
const heads = ref([
{ name: "参数", identifier: "attr" },
{ name: "类型", identifier: "type" },
]);
const keys = heads.value.map((item: any) => item.identifier);
const datas = ref([
{ attr: "level", type: "string" },
{ attr: "size", type: "string" },
{ attr: "loading", type: "boolean" },
]);
const del = (index) => {
datas.value = datas.value.filter((item, i) => i != index);
};
return { heads, keys, datas, del };
},
};
</script>

效果如图

效果图


感谢阅读

--It's the end.Thanks for your read.--