只需要,传如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>
<script setup lang="tsx">
const columns = reactive<ColumnProps<User.ResUserList>[]>([{
prop: "publishTime",
label: "发布时间",
width: 180,
render: (scope) => {
return <span>{scope.row.publishTime || "- -"}</span>
}
},
];
</script>
<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 表单组件我们 可以自定义任意组件放上面,并且可以在请求发出前,对参数进行特殊处理
参数 | 类型 | 是否必填 | 默认值 | 描述 |
---|---|---|---|---|
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 请求错误监听| |
参数 | 类型 | 是否必填 | 默认值 | 描述 |
---|---|---|---|---|
type | String | 否 | - | 对应列的类型("index" |
tag | Boolean | 否 | false | 前单元格值是否为标签展示,可通过 enum 数据中 tagType 字段指定 tag 类型 |
isShow | Boolean | 否 | true | 当前列是否显示在表格内(只对 prop 列生效) |
search | SearchProps | 否 | - | 搜索项配置,详情见 SearchProps |
enum | Array | Function | 否 | - |
fieldNames | Object | 否 | - | 指定 label && value && children 的 key 值 |
headerRender | Function | 否 | - | 自定义表头内容渲染(tsx 语法、h 语法) |
render | Function | 否 | - | 自定义表头内容渲染(tsx 语法、h 语法) |
参数 | 类型 | 是否必填 | 默认值 | 描述 |
---|---|---|---|---|
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 语法) |
参数 | 描述 |
---|---|
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() 即可获取最新列表数据
插槽 | 描述 |
---|---|
tableHeader | 自定义表格头部左侧区域的插槽,一般情况该区域放操作按钮 |
toolButton | 自定义表格头部左右侧侧功能区域的插槽 |
empty | 当表格数据为空时自定义的内容 |
pagination | 分页组件插槽 |