vue3 封装仿antd-vue的Table组件基本实现
作者:互联网
最近需要在不使用UI框架的情况下封装一个简单的表格,由于对antd-vue比较熟悉,所以仿照了antd-vue的样子写了个简化版的Table组件。
使用技术:VUE3、SCSS
用过antd-vue的都应该知道table组件主要的传参是两个:columns和dataSource,分别对应表头信息和表格的数据信息。
1.表头数据columns
表头的传参数据结构如下:
[
{ label: '姓名', key: 'name' },
{ label: '年龄', key: 'age' }
]
- key:必须,用来标志当前行
- label:非必须,当前列的列头显示内容
子组件-表头的遍历:
2.表格数据dataSource
表格数据传参的数据结构如下:
[
{name: '张三', age: 24},
{name: '李四', age: 45}
]
可以看到dataSource里面的key都是columns里面的key字段对应的值
对应源代码如下:
主要思路是先遍历每一行的数据,再在每一行的数据中根据columns遍历当前列的数据
做到这里不加66行的代码的话,整个表格显示功能就已经实现了。
3.添加操作功能
其实整个功能做起来比较简单,现在回想起来,还是自己对vue3的slot使用不太熟悉。
slot的基本使用见官网
这里能实现这个功能主要看的是作用域插槽的部分
代码还是看上面那张图的65、66两行。
但是columns的传参需要有变化:
[
{ label: '姓名', key: 'name' },
{ label: '年龄', key: 'age' },
{ label: '操作', key: 'operate', slots: 'operate'}
]
slots参数表示当前列需要使用插槽
父组件使用table组件:
<template #operate="record">
<a @click="handleOperate(record.rowData)">详情</a>
</template>
注意:
-
operate是v-slot的简化写法
- record是子组件内的slot插槽传过来的参数
- rowData与Table组件的:rowData对应,即当前tr的内容
接下来贴上使用代码:
可以看到使用基本和antd-vue差别不大了
4.其他功能
目前已经实现了表头固定table可滚动、宽度等基本功能、如果需要添加其他功能的话可以在此基础上添加各种传参即可
5.全部源码:
<template>
<div class="gw-table-content">
<!-- 需要表头固定,且表格可以滚动时的表头 -->
<table class="gw-fixed-table" v-if="tableHeaderFixed">
<thead
:style="{
backgroundColor: headerBackground
? 'hsla(200, 79%, 49%, 0.2)'
: 'transparent',
fontSize: headerFontSize || '18px'
}"
>
<th style="width:70px;" v-if="serialNumber">序号</th>
<th
:class="{ ellipsis: headerEllipsis }"
:width="h.width"
v-for="(h, i) in columns"
:key="i"
>
{{ h.label }}
</th>
</thead>
</table>
<div class="un-fixed-table-box">
<table class="gw-table">
<!-- 正常的表头,无固定 -->
<thead
v-if="!tableHeaderFixed"
:style="{
backgroundColor: headerBackground
? 'hsla(200, 79%, 49%, 0.2)'
: 'transparent',
fontSize: headerFontSize || '18px'
}"
>
<th style="width:70px;" v-if="serialNumber">序号</th>
<th
:class="{ ellipsis: headerEllipsis }"
:width="h.width"
v-for="(h, i) in columns"
:key="i"
>
{{ h.label }}
</th>
</thead>
<tbody>
<tr
:class="{ dash: trDash }"
v-for="(tr, ri) in dataSource"
:key="ri"
>
<!-- 是否需要序号 -->
<td style="width:70px;" v-if="serialNumber">{{ ri + 1 }}</td>
<td
:style="{
...td.style,
padding: tdPadding,
width: td.width
}"
v-for="(td, key) in columns"
:key="key"
>
<span :class="{ ellipsis: columnEllipsis }" :title="tr[td.key]">
<!-- 当前列的插槽, -->
<slot v-if="!td.slots">{{ tr[td.key] }}</slot>
<slot v-else :name="td.slots" :rowData="tr"></slot>
<!-- tr[td.key] 这个东西为什么能获取到当前这个key值的数据没太懂。。 -->
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script lang="js">
import { defineComponent } from 'vue'
export default defineComponent({
props: {
columns: {
// 表头
required: true,
default: []
},
dataSource: {
// 表数据
required: true,
default: []
},
serialNumber: {
// 是否需要第一列的序列号
required: false,
default: false
},
headerBackground: {
// 是否需要表头的背景色
required: false,
default: false
},
headerFontSize: {
// 表头字体大小
required: false,
default: ''
},
tdPadding: {
// td的padding值
required: false,
default: ''
},
headerEllipsis: {
// thead是否超过宽度省略
required: false,
default: true
},
columnEllipsis: {
// td是否超过宽度省略
required: false,
default: true
},
trDash: {
// 每行加下边框
required: false,
default: false
},
tableHeaderFixed: {
// 表头是否固定
required: false,
default: false
}
}
})
</script>
<style lang="scss" scoped>
.gw-table-content {
padding: 12px;
height: calc(100% - 21px);
.un-fixed-table-box {
max-height: calc(100% - 44px);
overflow-y: scroll;
}
.gw-table,
.gw-fixed-table {
width: 100%;
max-height: 100%;
position: relative;
table-layout: fixed;
thead {
background-color: #1ba0e1;
color: #00aaff;
font-family: 'Adobe Heiti Std R';
font-size: 17px;
th {
padding: 10px 12px;
font-family: Adobe Heiti Std;
font-weight: normal;
color: #00aaff;
}
th.ellipsis {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
tbody {
tr:nth-child(odd) {
background-color: rgba(27, 160, 225, 0.05);
}
tr {
overflow: hidden;
color: #00aaff;
td {
padding: 11px 12px;
font-size: 14px;
border-right: 2px solid transparent;
> span {
max-width: 100%;
display: inline-block;
}
> span.ellipsis {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}
tr.dash {
border-bottom: 1px dashed rgba(#1ba0e1, 0.3);
}
}
}
}
</style>
标签:vue,false,default,required,表头,label,key,vue3,Table 来源: https://www.cnblogs.com/codexlx/p/16392093.html