如此封装一个不一样的Table组件,让你的列表开发速度更快更优雅
也许你已经看过了「99」个 Table 组件的封装,但今天我们依然要为你介绍「第100」个 Table 组件的封装,快来看看和你之前看到的封装方式有什么不一样吧~
一、先看使用方式如上图,我们封装了一个不太一样的表格:
没有直接的传入表格列表格和分页组件是分开的表格内置了大量的事件支持还有很多...今天我们就来简单描述下,我们是如何一步步封装这个表格的。
二、表格基础泛型支持因为每个表格几乎都会对应到一个实体类,所以我们在封装表格的时候,也支持了泛型支持,如下所示:
scriptgeneric="E extends AirEntity"lang="ts"setup
其中AirEntity的定义,表示该数据具有「ID」属性,恰好对应了表格可能面对的一些有关单条数据的操作事件所需要的「主键ID」。
?当然,你如果真的没有 ID ,你可以使用前端的「UUID」来实现。
?三、定义表格基础属性一个后台业务的表格,至少应该包含以下的属性:
表格列表格数据加载状态...因为我们使用的是「TypeScript」+「装饰器」,所以我们在支持传入表格列的前提下,默认支持了直接从类配置的装饰器中获取标记了@Table()的属性作为表格列:
constprops = defineProps({
/**
* # 表格显示的数据数组
*/
dataList: {
type:Array,
required:true,
},
/**
* # 显示字段列表
* 如传入 则优先使用
*/
fieldList: {
type:ArrayAirTableFieldConfig,
default:()=[],
},
/**
* # 表格绑定的数据实体
*/
entity: {
type:FunctionasunknownasPropTypeClassConstructor,
required:true,
},
})
于是我们为表格添加了上面三个属性,其中:
3.1 dataListdataList作为表格数据的属性,对应为泛型数组的类型,且是必须传入的属性。
3.2 fieldListfieldList作为表格列的属性,对应为AirTableFieldConfig类型的数组,且是可选传入的属性,如果传入了该属性,则优先使用该属性作为表格列,否则将从下面的entity实体类中自动读取@Table()标记的属性作为表格列;
3.3 entityentity作为实体类的属性,对应为实体类的构造函数,且是必须传入的属性,用于从实体类中自动读取表格列。例如:entity="User",则从User类中读取@Table()标记的属性作为表格列。
如上实现了这三个属性之后,表格就可以这么使用了:
ATable
:data-list="list"
:entity="PermissionEntity"
/
scriptlang="ts"setup
constlist = refPermissionEntity[]([])
/script
当然,你可以自己传入fieldList:
ATable
:data-list="list"
:entity="PermissionEntity"
/
scriptlang="ts"setup
constlist = refPermissionEntity[]([])
constfieldList = computed(()={
returnPermissionEntity.getTableFieldList().filter(item={
// 隐藏其中某些列
returnitem.key !=='isDisabled'
})
// 当然,你也可以手动增加某些列
})
/script
而PermissionEntity则是表格列对应实体类的声明,包含了这个表格每行数据是什么类型:
@Model({
label:'权限',
})
exportclassPermissionEntityextendsBaseEntityimplementsITree {
@Table({
forceShow:true,
})
@Search()
@Form({
requiredString:true,
})
@Field({
label:'权限名称',
}) name!:string
@Table({
forceShow:true,
copyField:true,
})
@Form({
requiredString:true,
})
@Field({
label:'权限标识',
}) identity!:string
// 更多字段
}
这个类不仅承载了关于「表格」的部分,也有关于「表单」「搜索」等其他的公共内容,放到一个类中集中管理比较方便。
?本文就不再就「面向对象」声明数据结构展开了,这里争论点很多,欢迎阅读专栏内其他这部分的文章。
?四、表格的更多属性表格除了上述三个属性外,我们针对于业务还增加了非常多的属性:
constprops = defineProps({
/**
* # 是否隐藏编辑按钮
*/
hideEdit: {
type:Boolean,
default:false,
},
/**
* # 控制是否禁用行内编辑按钮的回调方法
*/
disableEdit: {
// eslint-disable-next-line no-unused-vars
type:FunctionasPropType(row: E) =boolean,
default:null,
},
/**
* # 是否隐藏序号
*/
hideIndex: {
type:Boolean,
default:false,
},
/**
* # 是否隐藏字段选择
* 如 `EntityConfig` 的 `hideFieldSelector` 设置为 `true`, 则此项失效
*/
hideFieldSelector: {
type:Boolean,
default:false,
},
...//太多了
})
上面只是举了些例子,如果你有兴趣,可以看看文章最后面的开源项目里的源代码。这里我们简单说明一下:
4.1 hideEdit 之类的隐藏或显示按钮配置我们可以使用hideEdithideDeleteshowEnableAndDisable等属性的配置来告诉Table组件需要支持显示一些按钮,如果按钮被点击的话,就会抛出相应的emits事件,后续会讲解这部分事件的处理。
4.2 hideFieldSelector 隐藏列选择器可以通过这个属性来配置是否为表格显示「列选择器」,选择列后,表格将只展示选择保存的部分列。
4.3 行回调事件属性有时候,某些行我们是不允许操作的,所以我们可以使用disableEditdisableDelete等属性来传入回调函数去控制这些操作,如下:
ATable
:disable-delete="row = row.isSystem"
:disable-edit="row = row.isSystem"
/
例如上面的,行数据如果满足指定的条件,功能将被禁用。
?其中,row的类型即为泛型表格组件的实体E类型。
?五、其他配置还支持了非常多的配置,比如「按钮权限标识」、「显示或隐藏部分功能」、「列宽度配置」、「更多按钮配置」、「懒加载」、「树表格」等等。
六、表格事件我们为表格支持了各种事件,用于表格某些功能触发后的回调处理:
constemits = defineEmits{
onDetail: [row: E],
onDelete: [row: E]
onEdit: [row: E]
onSelect: [list: E[]]
onAdd: [row: E]
onSort: [sort?: AirSort]
onDisable: [row: E]
onEnable: [row: E]
}()
事件处理的话这里就没什么好多说的了,只是我们基于 泛型组件 而提供的标准的事件(一定会回传一个带 ID 属性的事件参数而已)。
但也恰好因为我们提供的是泛型组件,于是我们基于这个组件提供了更方便操作的一些「hooks」:
七、表格Hooks首先,我们需要提供一个基础的表格hook:
7.1 airTableHook 表格基础Hook
如上图,我们提供了一个基础的表格 HookairTableHook,包含了表格的各种属性和事件,但不包含「增删改查」的部分。
提供了Hooks之后,我们也对一些关键事件节点提供了一些前后置方法,比如:
beforeSearch?:(requestData: AirRequestPage) =AirRequestPage |void
你可以基于这些前后置方法,轻松的在「增删改查」的过程中,做一些自定义的操作。
这个 Hook 是表格的基础,会被一般的「增删改查」表格组件 以及「选择类表格」所继承,于是有了下面俩子 Hook:
7.2 useAirTable 普通表格Hook
这个 Hook 基于表格基础Hook扩展了增删改查的功能,同时提供了一些常用的方法。
所以使用的地方也将更简单:
template
ATable
v-loading="isLoading"
:data-list="response.list"
:entity="UserEntity"
@on-edit="onEdit"
@on-delete="onDelete"
/
/template
scriptlang="ts"setup
const{
isLoading, response,
onEdit, onDelete,
} = useAirTable(UserEntity, UserService)
恰好因为我们使用了「面向对象」数据结构,所以response等都是对应UserEntity相应的数据请求响应类,取出的.list也是泛型UserEntity[]的标准数据数组结构。
7.3 useAirSelector 选择器表格Hook如上图,我们提供了选择器表格的 HookuseAirSelector,基于表格基础 Hook 扩展了选择器表格的功能,同时提供了一些选择器所使用的属性或方法。
当然,我们后续还提供了另外一个选择器专用的组件,和Table类似,封装最后使用起来更舒服了:
template
ASelector
:editor="UserEditor"
:entity="UserEntity"
:props="props"
:service="UserService"
/
/template
scriptlang="ts"setup
constprops = defineProps(airPropsSelectorUserEntity(newUserEntity()))
/script
这样就直接完成了一个用户的表格选择器,需要使用的时候,直接使用下面的方式就可以弹出这个选择器并获取选择之后的返回结果:
constuserList =awaitAirDialog.selectList(UserSelector)
美滋滋。
八、其他关联组件因业务需要,与表格也会存在很多的关联组件,比如:
8.1 ToolBar 工具栏组件工具栏组件中可能存在「新增」、「刷新」、「批量操作」等按钮,所以依然可以将useAirTable、useAirSelector等 Hook 返回的值作为参数传入,这样工具栏就可以直接联动这个 Hook 来与表格交互了。
工具栏还包含了「搜索」框,所以如果表格需要搜索功能,那么工具栏也会直接与表格联动。
8.2 Page 分页组件因为表格数据可能存在分页和不分页、树表格 等情况,所以 分页组件 被我们单独了出来,可以自行排列组合。
而且,我们的响应对象都被response做了封装,都可以方便的取出所需要的数据。
九、总结基于本文的内容,我们提供了非常丰富的表格组件、工具栏、分页 等组件,并提供了相应的「Hooks」支持,使得列表页面的开发更加的简单。
如果你对本文提到的内容感兴趣,可以关注我们的开源项目来阅读所有的源码:
Github:https://github.com/AirPowerTeam/AirPower-Web
Bye.
AI编程资讯AI Coding专区指南:
https://aicoding.juejin.cn/aicoding
点击"阅读原文"了解详情~
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线