前言
现如今开发后台管理界面比较多,表格数据展示、表单添加验证、表格查询条件几乎必不可少,但是大都是重复操作,所以封装了表格、表单和表格查询组件来减少代码重复量,后续会发布表单和表格查询组件。
提示:此案例基于element-plus封装,所以确保项目安装element-plus,且项目使用typescript,如果不想使用typescript,请直接移除所有的变量类型定义
以下是表格封装代码,可直接复制使用,具体表格参数可参考element-plus官方文档,如有其他要求,可直接在此基础上修改
<template>
<el-config-provider :locale="locale">
<div>
<el-table ref="table" :data="tableData" :max-height="maxHeight" v-loading="props.loading"
:border="border" highlight-current-row @current-change="currentChange"
@selection-change="selectionChange" :row-key="rowKey"
>
<el-table-column type="selection" width="55" v-if="selection" />
<el-table-column
min-width="50"
header-align="center"
align="center"
label="序号"
v-if="sort"
>
<template #default="scope">
<span>
{{
(Number(pageResult.current) - 1) * Number(pageResult.size) +
scope.$index +
1
}}</span>
</template>
</el-table-column>
<el-table-column
v-for="(item, index) in column"
:key="index"
align="center"
:label="item.label"
:prop="item.prop"
:min-width="item.minWidth"
:formatter="item.formatter"
show-overflow-tooltip
>
<!-- 如果该数据需要显示其他标签,则使用插槽显示 插槽名称就是column的prop -->
<template #default="scope" v-if="item.type">
<slot :name="item.prop" :row="scope.row"></slot>
</template>
</el-table-column>
<el-table-column
fixed="right"
label="操作"
align="center"
min-width="185"
v-if="option && !isSlotOption"
>
<template #default="scope">
<el-link
type="primary"
size="small"
@click="edit(scope.row)"
:underline="false"
style="margin-right: 5px"
>编辑</el-link
>
<el-popconfirm title="是否删除" @confirm="confirm(scope.row)">
<template #reference>
<el-link type="danger" :underline="false">删除</el-link>
</template>
</el-popconfirm>
</template>
</el-table-column>
<el-table-column
v-if=" option && isSlotOption"
fixed="right"
label="操作"
align="center"
min-width="185"
>
<template #default="scope">
<slot name="option" :row="scope.row"></slot>
</template>
</el-table-column>
</el-table>
<div class="demo-pagination-block" v-if="props.pagination">
<el-pagination
v-model:current-page="pageResult.current"
v-model:page-size="pageResult.size"
:page-sizes="[10, 20, 30, 50]"
layout="total, sizes, prev, pager, next, jumper"
:total="pageResult.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</el-config-provider>
</template>
<script setup lang="ts">
import {ref,useSlots,computed} from 'vue'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
const locale = zhCn
interface pageObj {
size:number,
current:number,
total:number
}
interface columnObj {
label:string,
prop:string,
type?:string,
formatter?:Function,
minWidth?:string,
[key:string]:any
}
const table = ref()
const slots = useSlots()
const isSlotOption = computed(() => {
return slots.option?true:false
})
const props = withDefaults (
defineProps <{
tableData: Array<{ [key:string]:any}>,
loading?:boolean,
border?:boolean,
maxHeight?:string,
selection?:boolean,
pageResult?:pageObj,
sort?:boolean,
option?:boolean,
column:Array<columnObj>,
pagination?:boolean,
rowKey?:string
}> (), {
// 表格数据
tableData: () => {
return []
},
// 表格加载状态
loading:false,
// 表格最大高度
maxHeight:'550px',
// 是否带有纵向边框
border:false,
// 是否多选
selection:false,
// 分页页数和每页显示
pageResult:() => {
return {size:10,current:1,total:0}
},
// 是否显示序号(1,2,3,4,5)
sort:true,
// 表格内容
column:() => {
return []
},
// 是否显示操作模块
option:true,
// 是否显示分页
pagination:() => {
return true
},
rowKey:''
})
const emits = defineEmits(['edit','confirm','handleSizeChange','handleCurrentChange',
'currentChange','selectionChange'
])
// 点击编辑按钮
const edit = (row) => {
emits('edit',row)
}
// 确认删除
const confirm = (row) => {
emits('confirm',row)
}
// 分页
const handleSizeChange = (val:number) => {
emits('handleSizeChange',val)
}
const handleCurrentChange = (val:number) => {
emits('handleCurrentChange',val)
}
// 选中单行
const currentChange = (val) => {
emits('currentChange',val)
}
// 多行
const selectionChange = (val) => {
emits("selectionChange", val);
}
defineExpose({table})
</script>
<style scoped>
.demo-pagination-block {
display: flex;
justify-content: flex-end;
padding: 20px 0;
padding-right: 20px;
}</style>
注意:由于element-plus本身显示的文字是英文,所以需要el-config-provider将其转换(详情见官方文档,如果你在路由已经添加el-config-provider,这里可以将其去掉)
使用方式
<template>
<kt-table :tableData="common.tableData" :column="common.column" :sort="true">
<template #status="row">
<!-- 可写其他标签样式,这里只是展示 -->
<span>{{ row.row }}</span>
</template>
<template #option="row">
<!-- 可写其他操作样式,这里只是展示 -->
<span>123{{ row.row }}</span>
</template>
</kt-table>
</template>
<script setup lang="ts">
interface columnObj {
label:string,
prop:string,
type?:string,
formatter?:Function,
minWidth?:string,
[key:string]:any
}
const common = reactive({
text: '',
tableData: [{serviceCcicId:'111111',businessStatus:'10'}],
column: [
{ label: '服务项编号', prop: 'serviceCcicId' },
{
label: '服务项状态', prop: 'businessStatus', formatter: (row) => {
return row.businessStatus == 0 ? '未开工' : (row.businessStatus == 10 ? '实施中' : (row.businessStatus == 20 ? '完工审核' : (row.businessStatus == '30' ? '已完工' : '其他')))
}
},
{ label: '任务单状态', prop: 'status', type: 'html', minWidth: '200px' },
] as columnObj[]
})
</script>
<style lang='scss' scoped></style>
注意:使用组件需先引入组件,这里没有引入是因为已经将该组件引入在全局当中
npm下载:npm i cc-element-component