element-plus-table
v1.0.7
Published
基于 Vue3、Element Plus 开发的一款表格组件,对Element Plus的el-table进行二次封装
Downloads
1
Maintainers
Readme
基于 Vue3、Element Plus 开发的一款表格组件,对 Element Plus 的 el-table 进行二次封装
只需要,传如columns,和接口即可把后台的表单搜索项,列表,及分页渲染出了,并支持自定义内容,可以提高开发效率30%左右。
TablePlus 组件上的绑定的所有属性和事件都会通过 v-bind="$attrs" 透传到 el-table 上。 TablePlus 组件内部暴露了 el-table DOM,可通过 TablePlus.value.element.方法名 调用其方法 也就是说你想使用 el-table 的任何属性、事件,目前通过属性透传都能支持。
安装
npm install element-plus-table -S
项目中引入
import { createApp } from 'vue'
import App from './App.vue'
import TablePlus from "element-plus-table"
const app = createApp(App);
app.use(TablePlus)
app.mount('#app')
在项目中使用入门案例
<template>
<TablePlus
ref="tablePlus"
title="列表"
:columns="columns"
:request-api="getTableList"
row-key="articleId"
></TablePlus>
</template>
<script setup lang="tsx">
import { ref } from "vue"
const rowItem = {
articleId: 0,
title: "文章标题",
origin: 1,
publishTime: "2024-09-01 12:00:00",
publishStatus: 2
}
type rowItemType = typeof rowItem
interface paramsReq {
pageSize: number
pageNum: number
}
const tablePlus = ref()
// 模拟获取列表接口
const articleList = (params: paramsReq) => {
return new Promise((resolve) => {
const entities: rowItemType[] = []
for (let i = 0; i < 10; i++) {
entities.push({
articleId: i,
title: "文章标题" + i,
origin: 1,
publishTime: "2024-09-01 12:00:00",
publishStatus: 2
})
}
const ressult = {
total: 100,
pageNum: params.pageNum,
pageSize: params.pageSize,
list: entities
}
setTimeout(() => {
resolve(ressult)
}, 1500)
})
}
const getTableList = (params: paramsReq) => {
const newParams = JSON.parse(JSON.stringify(params))
// 请求前参数可以在这里处理
return articleList(newParams)
}
// 表格配置项
const columns = [
{ type: "index", label: "序号", width: 80 },
{
prop: "title",
label: "文章标题0"
},
{
prop: "title",
label: "文章标题1",
search: {
el: "input",
props: { maxlength: 30, placeholder: "请输入文章标题1" }
}
}
]
</script>
稍微复杂点案例
<template>
<TablePlus
ref="tablePlus"
title="列表"
:columns="columns"
:request-api="getTableList"
:init-param="initParam"
:pagination="true"
:data-callback="dataCallback"
:reset-callback="resetCallback"
row-key="articleId"
>
<!-- 表格 header 按钮 -->
<template #tableHeader="scope">
<el-button type="primary" :icon="CirclePlus" class="mb10">新建</el-button>
<el-button
type="primary"
plain
:disabled="!scope.isSelected"
class="mb10"
@click="batchPublish(scope.selectedListIds, 2)"
>
批量发布
</el-button>
<el-button
type="danger"
:icon="Delete"
plain
:disabled="!scope.isSelected"
class="mb10"
@click="batchDelete(scope.selectedListIds)"
>
批量删除
</el-button>
</template>
<!-- 表格操作 -->
<template #operation="scope">
<el-button
type="primary"
link
:icon="EditPen"
@click="openDrawerEdit(scope.row)"
>
编辑
</el-button>
<el-button type="primary" link :icon="Delete">删除</el-button>
</template>
</TablePlus>
</template>
<script setup lang="tsx">
import { ref, reactive } from "vue"
import { CirclePlus, Delete, EditPen } from "@element-plus/icons-vue"
const rowItem = {
articleId: 0,
title: "文章标题",
origin: 1,
publishTime: "2024-09-01 12:00:00",
publishStatus: 2
}
type rowItemType = typeof rowItem
interface paramsReq {
pageSize: number
pageNum: number
}
const tablePlus = ref()
const initParam = reactive({
type: "yyy",
pageSize: 10,
hotWordList: []
})
// 模拟获取列表接口
const articleList = (params: paramsReq) => {
return new Promise((resolve) => {
const entities: rowItemType[] = []
for (let i = 0; i < 10; i++) {
entities.push({
articleId: i,
title: "文章标题" + i,
origin: 1,
publishTime: "2024-09-01 12:00:00",
publishStatus: 2
})
}
const ressult = {
total: 100,
pageNo: params.pageNum,
pageSize: params.pageSize,
entities
}
setTimeout(() => {
resolve(ressult)
}, 1500)
})
}
const dataCallback = (data: any) => {
data?.entities.forEach((item: any) => {
item.mechanismValue = [item.category, item.column]
})
return {
list: data?.entities,
total: data.total,
pageNum: data.pageNo,
pageSize: data.pageSize
}
}
const getTableList = (params: paramsReq) => {
const newParams = JSON.parse(JSON.stringify(params))
// 请求前参数可以在这里处理
return articleList(newParams)
}
// 批量删除用户信息
const batchDelete = async (articleIds: string[]) => {
console.log("articleIds", articleIds)
// await fetchAPI()
tablePlus.value?.clearSelection()
tablePlus.value?.getTableList()
}
const batchPublish = async (articleIds: string[], status: number) => {
console.log("articleIds: string[], status: number", articleIds, status)
// await fetchAPI()
tablePlus.value?.clearSelection()
tablePlus.value?.getTableList()
}
// 表格配置项
const columns = [
{ type: "selection", fixed: "left", width: 80 },
{ type: "index", label: "序号", width: 80 },
{
prop: "title",
label: "文章标题0"
},
{
prop: "title",
label: "文章标题",
search: {
el: "input",
props: { maxlength: 30, placeholder: "请输入文章标题" }
}
},
{
prop: "title",
label: "文章标题2",
search: {
el: "input",
order: 10,
props: { maxlength: 30, placeholder: "请输入文章标题2" }
}
},
{
prop: "title",
label: "文章标题3",
isShow: false,
search: {
el: "input",
order: 1,
props: { placeholder: "请输入文章标题3" }
}
},
{
prop: "origin",
label: "数据来源",
width: 160,
enum: [
{
label: "文章库",
value: 1
},
{
label: "自建新增 ",
value: 2
}
],
search: { el: "tree-select", props: { filterable: true } }
},
{
prop: "publishTime",
label: "发布时间",
width: 180,
render: (scope) => {
return <div>{scope.row.publishTime || "- -"}</div>
}
},
{
prop: "publishStatus",
label: "是否发布",
width: 160,
enum: [
{
label: "已发布",
value: 2
},
{
label: "未发布",
value: 1
}
],
search: { el: "tree-select", props: { filterable: true } },
render: (scope) => {
return (
<>
<el-switch
model-value={scope.row.publishStatus}
active-text={scope.row.publishStatus === 2 ? "已发布" : "未发布"}
active-value={2}
inactive-value={1}
onClick={doPublish}
/>
</>
)
}
},
{ prop: "operation", label: "操作", fixed: "right", width: 200 }
]
const resetCallback = () => {
console.log("resetCallBack")
initParam.hotWordList = []
tablePlus.value?.getTableList()
}
// 上架
const doPublish = async (params: any) => {
console.log("doPublish", params)
// await fetchAPI()
tablePlus.value?.getTableList()
}
const openDrawerEdit = async (row: Partial<any>) => {
console.log(row)
}
</script>
<style scoped>
.mb10 {
margin-bottom: 10px;
}
</style>
表格中每一项都可以都可以通过render可使用 tsx 组件自定义渲染
<script setup lang="tsx">
const columns = reactive<ColumnProps<User.ResUserList>[]>([{
prop: "publishTime",
label: "发布时间",
width: 180,
render: (scope) => {
return <span>{scope.row.publishTime || "- -"}</span>
}
},
];
</script>
表格搜索项可使用 tsx 组件自定义渲染
<script setup lang="tsx">
const columns = reactive<ColumnProps<User.ResUserList>[]>([
{
prop: "score",
label: "分数",
search: {
// 自定义 search 组件
render: ({ searchParam }) => {
return (
<div>
<el-input vModel_trim={searchParam.minAge} placeholder="最小分数"/>
<span>-</span>
<el-input vModel_trim={searchParam.maxAge} placeholder="最大分数" />
</div>
);
}
}
},
];
</script>
也就是说search 表单组件我们 可以自定义任意组件放上面,并且可以在请求发出前,对参数进行特殊处理
TablePlus 属性
| 参数 | 类型 | 是否必填 | 默认值 | 描述| | -------- | :-----: | :-----: | :-----: | :---- | | columns | ColumnProps| 是 | [] | TablePlus 组件会根据此字段渲染搜索表单与表格列(支持动态更新)| | request-api | Function | 否 | - | 获取表格数据的请求 API | | data | Array | 否 | - | 静态 tableData 数据(支持分页),若存在则不会使用 request-api 返回的 data| | data-callback | Function | 否 | - | 后台返回数据的回调函数,可对后台返回数据进行处理| | reset-callback | Function | 否 | - | 用户点击重置按钮的回调函数,可对搜索表单进行参数进行特殊处理| | pagination | Boolean | 否 | - | 是否显示分页组件:pagination 为 false 后台返回数据应该没有分页信息 和 list 字段,data 就是 list 数据 | initParam | Object | 否 | {} | 表格请求的初始化参数,该值变化会重新请求表格数据 | rowKey | String | 否 | 'id' | 当表格数据多选时,所指定的 id | tableSearchColumns | ColumnProps| 否 | [] | TablePlus 组件会根据此字段渲染搜索表单支持动态更新)有这个参数后就会上面表单就会用这个参数去渲染| | request-error | Function | 否 | - | 表格 API 请求错误监听|
Column 配置(ColumnProps 属性)
| 参数 | 类型 | 是否必填 | 默认值 | 描述| | -------- | :-----: | :-----: | :-----: | :---- | | type | String| 否 | - | 对应列的类型("index" | "selection" | "radio" | "expand" | "sort"))| | tag | Boolean| 否 | false | 前单元格值是否为标签展示,可通过 enum 数据中 tagType 字段指定 tag 类型| | isShow | Boolean| 否 | true | 当前列是否显示在表格内(只对 prop 列生效)| | search | SearchProps| 否 | - | 搜索项配置,详情见 SearchProps| | enum | Array | Function| 否 | - | 可格式化单元格内容,还可以作为搜索框的下拉选项(字典可以为 API 请求函数,内部会自动执行)| | fieldNames | Object| 否 | - | 指定 label && value && children 的 key 值| | headerRender | Function| 否 | - | 自定义表头内容渲染(tsx 语法、h 语法)| | render | Function| 否 | - | 自定义表头内容渲染(tsx 语法、h 语法)|
搜索项 配置(SearchProps):
| 参数 | 类型 | 是否必填 | 默认值 | 描述| | -------- | :-----: | :-----: | :-----: | :---- | | el | String| 否 | - | 当前项搜索框的类型,支持:input、input-number、select、select-v2、tree-select、cascader、date-picker、time-picker、time-select、switch、slider)| | labelString | String| 否 | - | 当搜索项 label,如果不指定默认取 column 的 label| | props | Object| 否 | - | 根据 element plus 官方文档来传递,通过属性透传将 search.props 属性全部透传到每一项搜索组件上,所以我们支持 input、select、tree-select、date-packer、time-picker、time-select、switch 大部分属性| | key | String| 否 | - | 当搜索项 key 不为 prop 属性时,可通过 key 指定| | order | Number| 否 | - | 搜索项排序(从小到大)| | key | String| 否 | - | 当搜索项 key 不为 prop 属性时,可通过 key 指定| | defaultValue | Any| 否 | - | 搜索项默认值(该值重置时会重置回初始值)| | render | Function| 否 | - | 自定义搜索内容渲染(tsx 语法、h 语法)|
TablePlus 的方法:
| 参数 | 描述| | -------- | ----: | | element | el-table 实例,可以通过TablePlus.value.element.***()来调用 el-table 的所有方法)| | getTableList | 获取、刷新表格数据的方法(携带所有参数)| | tableData | 当前页面所展示的数据| | pageable | 当前表格的分页数据| | searchParam | 所有的搜索参数,不包含分页| | searchInitParam | 所有的搜索初始化默认的参数| | search | 表格查询方法,相当于点击搜索按钮| | reset | 重置表格查询参数,相当于点击重置按钮| | handleSizeChange | 表格每页条数改变触发的事件| | handleCurrentChange | 表格当前页改变触发的事件| | clearSelection | 清空表格所选择的数据| | enumMap | 当前表格使用的所有字典数据(Map 数据结构)| | isSelected | 表格是否选中数据| | selectedList | 表格选中的数据列表| | selectedListIds | 表格选中的数据列表的id|
如 在组件中 tablePlus.value?.getTableList() 即可获取最新列表数据
TablePlus 插槽:
| 插槽 | 描述| | -------- | ----: | | tableHeader | 自定义表格头部左侧区域的插槽,一般情况该区域放操作按钮| | toolButton | 自定义表格头部左右侧侧功能区域的插槽| | empty | 当表格数据为空时自定义的内容| | pagination | 分页组件插槽|