前言
我们在使用UI库编写页面的时候,特别是账务系统,需要用到表格的情况会比较多,如果我们每次都是复制一遍UI库中的demo然后进行调整,这样造成的结果是多次引入 Table 组件,而且从前端开发规范来讲,不符合组件化的初衷。因此我们将 Table 组件进行二次封装,无疑是最好的选择。二次封装 Table 组件就是为了增强组件的可复用性、可维护性和功能性。
二次封装的优势
-
统一风格和功能
- 样式一致性:项目中可能有多个地方使用表格,二次封装可以确保所有表格在样式和功能上保持一致。
-
简化使用
- 简化 API:通过封装,可以提供更简单、更直观的 API,减少开发者在使用时需要考虑的细节。例如,可以通过 props 传递配置选项,而不必每次都重复编写配置。
- 封装复杂逻辑:将复杂的逻辑(例如数据处理、列渲染)封装到一个组件中,调用方只需使用这个封装的组件即可,降低了使用难度。
-
增强功能
- 插槽:通过插槽,可以灵活地扩展表格的功能,例如自定义列内容、操作按钮等,提升组件的灵活性。
- 事件处理:可以统一处理表格中的各种事件,如行点击、行选中等,提供更一致的事件响应方式。
-
提高可维护性
- 集中管理:将表格的所有相关逻辑集中到一个地方,使得后续的维护和修改更加简单。如果需要更改某个功能,只需在封装的组件中进行修改,而不必在每个使用表格的地方重复修改。
- 易于调试:封装后的组件可以更容易进行单元测试和调试,确保表格的各项功能在不同场景下都能正常工作。
-
提高开发效率
- 复用性:封装后的组件可以在不同的项目中复用,节省开发时间。通过封装常用的表格功能,可以减少重复劳动。
- 快速迭代:通过提供易于使用的组件,团队成员可以快速上手并使用,而不必深入了解底层实现。
我使用的技术栈是Vue3+Ts+Element Plus,所以此次table组件的二次封装也是基于Element Plus的,其中Element Plus版本选的是2.8.0。
前提条件
默认大家已经能够正确地创建Vue3+Ts的前端工程,Element Plus的安装可以参考https://element-plus.org/zh-CN/guide/installation.html,还需要大家在提前注册Element Plus所有的图标。代码如下:
// main.ts
import * as ElementPlusIconsVue from '@element-plus/icons-vue';
// 注册elementPlus所有的图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
封装代码源码
// c-table/components/table-column-item/index.vue
<template>
<el-table-column
v-if="!column.children && column.type !== 'selection' && column.type !== 'expand'"
:prop="column.prop"
:label="column.label"
:width="column.width"
:show-overflow-tooltip="column.showOverflowTooltip"
:fixed="column.fixed"
:min-width="column.minWidth"
:align="column.align"
:type="column.type"
:resizable="column.resizable"
:sortable="column.sortable"
:selectable="column.selectable"
:column-key="column.columnKey"
:filters="column.filters"
:filter-method="column.filterMethod"
:sort-method="column.sortMethod"
:sort-by="column.sortBy"
:sort-orders="column.sortOrders"
:header-align="column.headerAlign"
:class-name="column.className"
:label-class-name="column.labelClassName"
:reserve-selection="column.reserveSelection"
:filter-placement="column.filterPlacement"
:filter-class-name="column.filterClassName"
:filter-multiple="column.filterMultiple"
:filter-value="column.filterValue"
>
<template #default="{ row, $index }">
<template v-if="column.formatter">
<template v-if="isStringFormatter(row, $index)">
{
{
column.formatter(row, column, row[column.prop], $index)
}}
</template>
<template v-else>
<component
:is="
column.formatter(
row,
column,
row[column.prop],
$index
)
"
/>
</template>
</template>
<template v-if="column.index && !column.formatter">
{
{ column.index($index) }}
</template>
<component
:is="column.slots.default"
:row="row"
:index="$index"
v-if="column.slots && column.slots.default"
/>
</template>
<template #header="scope" v-if="column.slots && column.slots.header">
<component
:is="column.slots.header"
:row="scope.row"
:index="scope.$index"
/>
</template>
</el-table-column>
<!-- 多级表头 -->
<el-table-column
v-if="column.children && column.type !== 'expand'"
:prop="column.prop"
:label="column.label"
:align="column.align"
:type="column.type"
:resizable="column.resizable"
>
<template v-for="child in column.children" :key="child.prop">
<table-column-item :column="child" />
</template>
</el-table-column>
<!-- 多选 -->
<el-table-column
v-if="column.type == 'selection'"
type="selection"
:width="column.width"
:selectable="column.selectable"
/>
<!-- 展开行 -->
<el-table-column v-if="column.type == 'expand'" type="expand">
<template #default="{ row, $index }">
<component
:is="column.slots.default"
:row="row"
:index="$index"
/>
</template>
</el-table-column>
</template>
<script lang="ts">
import { PropType } from "vue";
import { ColumnItem } from "../../../../type";
import { ElTable, ElTableColumn } from "element-plus";
export default {
name: "TableColumnItem",
props: {
column: {
type: Object as PropType<ColumnItem>,
default: {},
},
},
components: {
ElTableColumn,
},
setup(props, context) {
const isStringFormatter = (row: any, index: number): boolean => {
const formattedValue = props.column.formatter(
row,
props.column,
row[props.column.prop],
index
);
return typeof formattedValue === "string";
};
retur

最低0.47元/天 解锁文章
2332

被折叠的 条评论
为什么被折叠?



