来个一个全新的小项目,vue3出来这么久了,可以实践起来!
对于一个后台管理系统来说,表格组件是不可缺少的。面对大量的表格,就得尽可能的复用组件。让我们提升技术的同时更好的摸鱼。嘿嘿。
话不多说,开干!
首先默认已经安装了element-plus,封装好了统一的axios,因为用上了typescript(刚学的),用的不好轻喷
table组件
<div class="table">
<el-table ref="TableComponents"
:header-cell-style="{background:'#F7F7F7',color:'#333'}"
:size="size" :border="border" :data="tableData"
:tree-props="treeProps"
:fit="fit"
:max-height="maxHeight"
:row-key="rowKey"
:highlight-current-row="true"
:automatic-dropdown="false"
@selection-change="handleSelectionChange"
>
<template v-for="item in columns" :key="item.prop">
<slot :name="item.slot" v-if="item.slot&&item[dataKey.label]"></slot>
<el-table-column :prop="item[dataKey.prop]" show-overflow-tooltip :label="item[dataKey.label]" v-if="item[dataKey.label]&&!item.slot" :formatter="item.formatter" :min-width="item.width">
</el-table-column>
<el-table-column type="selection" width="55" v-if="!item[dataKey.label]&&!item.slot" :selectable="checkSelectable"></el-table-column>
</template>
<slot name="operation"></slot>
</el-table>
<el-pagination
v-if="pageIsShow&&pageTotal>10" class="pagination"
:size="size" :page-sizes="pageSizes" :page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pageTotal" :current-page="currentPage"
@size-change="handleSizeChange" @current-change="handleCurrentChange"
>
</el-pagination>
</div>
</template>
<script lang="ts">
import { defineComponent, watch } from 'vue'
export default defineComponent({
name:'table',
props:{
loading:{
type:Boolean,
default:true
},
tableData:{
type:Array,
default:[] //表格数据
},
columns:{
type:Array,
default:()=>[]//表格列
},
pageIsShow:{
type:Boolean,
default:true //是否显示分页
},
pageSizes:{
type:Array,
default:()=>[10, 15, 20,30,50,100] //智能分页选项
},
pageSize:{
type:Number,
default:()=>10 //默认每页条数
},
pageTotal:{
type:Number,
default:()=>0 //总条数
},
border:{
type:Boolean,
default:true //默认有边框
},
stripe:{
type:Boolean,
default:true //是否为斑马纹 table(默认有)
},
fit:{
type:Boolean,
default:true //默认自动撑开
},
size:{
type:String,
default:'small'
},
treeProps:{
type:Object,
default:()=>{}
},
rowKey:{
type:String||Function,default:()=>''
},
dataKey:{
type:Object,
default:()=>{
return {label:'label',prop:'prop'}
}
},
currentPage:{
type:Number,
default:()=>1 //当前页码
},
height:{
type:String,
default:'55px'
},
maxHeight:{
type:Number,
default:()=> {
return document.body.offsetHeight-210
}
}
},
setup(props, ctx) {
const { emit } = ctx;
const handleSelectionChange = (val: any) => emit('selection-change', val);
const handleSizeChange = (val: number) => emit('size-change', val);
const handleCurrentChange = (val: number) => emit('current-change', val);
const handleClickActiveLink = ($event: MouseEvent, row: any) => emit('get-row-info', $event, row);
const checkSelectable = (row: any) => row.name !== 'None';
return {
handleSelectionChange,
handleSizeChange,
handleCurrentChange,
handleClickActiveLink,
checkSelectable
}
},
})
</script>
<style lang="scss" scoped>
.table{
.pagination{
margin-top: 10px;
text-align: right;
padding-left: 20px;
}
}
</style>
然后是hooks.ts
import { onMounted, reactive } from 'vue'
import { HttpListQuery, IdParam } from '@/@types/index' //这个是定义的泛型
/**
export interface HttpListQuery {
pageNo: number
pageSize: number
[key: string]: any
}
export interface IdParam {
id: number
}
export interface HttpResponse {
code: number
status: number
statusText: string
result: any
}
**/
import CommonService from '@/api/common' //这几个是统一封装的方法
class CommonService {
//获取列表
static async getTableList(url:string,data:HttpListQuery): Promise<HttpResponse> {
return Axios(url,{
method: 'post',
headers: {
'Content-Type': 'application/json'
},
data
})
}
static async deleteItem(url:string,data:IdParam): Promise<HttpResponse> {
return Axios(url,{
method: 'post',
headers: {
'Content-Type': 'application/json'
},
data
})
}
}
**/
import { successMessage } from "@/utils/message";//消息提示
interface Params{
searchUrl: string //搜索api地址
deleteUrl: string //删除的api地址
searchData: any //搜索的数据
}
const useTable = (options:Params) => {
let { searchUrl, deleteUrl, searchData} = options
//搜索数据滴响应
const searchState = reactive({
searchData,
pageNo: 1,
pageSize: 10,
})
//返回数据滴响应
const dataState = reactive({
tableData: [],
total:0
})
//获取表格数据
const getTableList = async (Params:HttpListQuery) => {
let { code, result } = await CommonService.getTableList(searchUrl, Params)
if(code === 200) {
dataState.tableData = result.records
dataState.total = result.total
}
}
//引入生命周期,执行搜索
onMounted(()=>{
getTableList({...searchState})
})
//删除某一行数据
const deletaItem = async (deleteId:IdParam) => {
let { code, result} = await CommonService.deleteItem(deleteUrl,deleteId)
if(code === 200) {
successMessage('删除成功')
getTableList(searchState)
}
}
//调整每一页多少行数据
const sizeChange = (val:number) => {
searchState.pageNo = 1;
searchState.pageSize = val;
getTableList(searchState)
}
//翻页的
const currentChange = (val:number) =>{
searchState.pageNo = val;
getTableList(searchState)
}
return {
searchState,
dataState,
getTableList,
deletaItem,
sizeChange,
currentChange
}
}
export default useTable;
基础的完成了,接下来就是在组件中调用,映入组件和hooks
//模板
<Table :columns="columns" :tableData="tableData" :page-total="total" @size-change="sizeChange" @current-change="currentChange">
<template #operation>
<el-table-column label="操作" fixed="right" :width="150">
<template v-slot="scope">
<div class="table-operation">
<span type="text" class="text-btn" >
<el-popconfirm
confirmButtonText='好的'
cancelButtonText='不用了'
icon="el-icon-info"
iconColor="red"
title="确定删除选中xxx吗?"
@confirm="delete(scope.row.id)"
>
<template #reference>
<span>删除</span>
</template>
</el-popconfirm>
</span>
</div>
</template>
</el-table-column>
</template>
</Table>
//ts
<script lang="ts">
//定义表格响应数据的
export default defineComponent({
components:{Table},
setup() {
const tableState = reactive({
searchParams: {
typeName: '',
typeCode:''
},
columns: [
{prop: 'XXX', label: 'XXX',width:180},
{prop: 'XXX', label: 'XXX'},
{label: '操作', slot:'operate'}
]
})
const params = {
searchUrl: 'XXX',
deleteUrl:'XXX',
searchData: tableState.searchParams
}
const {
getTableList,
deletaItem,
sizeChange,
currentChange,
searchState,
dataState,
} = useTable(params) //使用hooks
//给搜索按钮加上的事件
const getPageList = ():void => {
getTableList({...searchState})
}
//删除方法
const delete = async (id:number) => {
deletaItem({id})
}
return {
...toRefs(tableState),
...toRefs(searchState),
...toRefs(dataState),
getPageList,
sizeChange,
currentChange,
delete
}
}
})
</script>
第一次发文,不当之处见谅。技术有限,请多多指教!