从零开始vue3+vite+ts+pinia+router4后台管理(5)-二次封装表格1.0
项目地址
思路和原则
二次封装UI组件要注意的三个地方分别是属性、事件、插槽,我们在封装组件的时候,无非是往这个方向,我们在封装的时候不能影响 原UI组件原有的属性、事件,插槽的前提下,然后在其基础上做二次封装,这是一个必须的原则,如果影响了原来的UI组件那就不是一个好的封装
页面可以分为4个模块
- 表格搜索区域
- 表格数据操作按钮区域
- 表格主体内容展示区域
- 表格分页区域
基本实现
table.vue
<template>
<div class="app-container">
<div class="filter-container">
<el-input class="w-100" v-model="queryForm.keyword" placeholder="关键字搜索" />
<el-button type="primary" :icon="Search" @click="handleSearch">搜索</el-button>
<el-button class="green-button" :icon="Plus" @click="handleSearch">增加</el-button>
</div>
<div class="table-con">
<el-table
v-loading="loading"
:data="tableData"
style="width: 100%"
row-key="id"
border
>
<el-table-column prop="staffName" label="姓名"/>
<el-table-column prop="name" label="name"/>
<el-table-column prop="title" label="title"/>
<el-table-column prop="phone" label="联系方式"/>
<el-table-column prop="address" label="地址"/>
<el-table-column prop="startDate" label="日期"/>
<el-table-column fixed="right" label="操作" width="120">
<template #default>
<el-button link type="primary" size="small">修改</el-button>
<el-button link size="small">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<Pagination
v-model:page="pagination.page"
v-model:size="pagination.pageSize"
:total="total"
@pagination="getTableData"
/>
</div>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import { Search,Plus } from '@element-plus/icons-vue'
import {useTable} from '@/hooks/useTable'
import tableApi from '@/api/table'
const queryForm = reactive({
keyword: ''
})
const {
tableData,
pagination,
total,
loading,
getTableData,
handleSearch//搜索
} = useTable(tableApi.packTableList)
</script>
<style scoped>
.w-100{
width: 200px;
margin-right: 5px;
}
</style>
hooks/useTable.ts
import { reactive, onMounted,ref } from 'vue'
export function useTable(loadDataFunc: Function) {
let loading = ref(true)
let tableData = ref()
let total = ref(0)
const pagination = reactive({
page: 1,
pageSize: 10
})
const getTableData = async () => {
loading.value = true;
const res = await loadDataFunc({...pagination})
tableData.value = res.data.list;
total.value = res.data.total
loading.value = false;
}
onMounted(() => {
getTableData()
})
// 搜索
const handleSearch = () => {
pagination.page = 1
getTableData()
}
return {
loading,
tableData,
total,
pagination,
handleSearch
}
}
分页的实现 components/Pagination.vue
<!-- 分页el-pagination 二次封装 -->
<template>
<div v-show="total>0" class="pagination-con">
<el-pagination
v-model:current-page="curPage"
v-model:page-size="pageSize"
:page-sizes="[10, 20, 30, 40, 50]"
background
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script setup name="Pagination" lang="ts">
import { ref,computed} from 'vue'
const props = defineProps({
page: { type: Number, default: 1 },
size: { type: Number, default: 10 },
total: { type: Number, default: 0 }
})
// 1、在子组件中调用defineEmits并定义要发射给父组件的方法
// 2、使用defineEmits会返回一个方法,使用一个变量emit(变量名随意)去接收
// 3、在子组件要触发的方法中,调用emits并传入发射给父组件的方法以及参数
const emit = defineEmits(['update:size', 'update:page', 'pagination'])
const pageSize = computed({
get: () => props.size,
set: (val) => {
emit('update:size', val)
}
})
const curPage = computed({
get: () => props.page,
set: (val) => {
emit('update:page', val)
}
})
function handleSizeChange() {
emit('pagination')
}
function handleCurrentChange() {
emit('pagination')
}
</script>
<style scoped>
.pagination-con{
margin-top: 10px;
margin-bottom: 10px;
}
</style>
分页要注意的两个地方
1 全局注册 分页main.ts
import { createApp } from 'vue' //引入vue
const app = createApp(App)// 创建vue实例
import Pagination from '@/components/Pagination.vue'//引入分页组件
app.component('Pagination', Pagination)//注册分页
2.element plus 全局中英文显示
element plus 默认是英文显示
默认的分页样式
要改成中文需要在入口文件App.vue 下面修改zh是中文 en是英文
<template>
<el-config-provider :locale="zh">
<router-view></router-view>
</el-config-provider>
</template>
<script setup lang="ts">
import { ElConfigProvider } from 'element-plus'
import zh from 'element-plus/es/locale/lang/zh-cn'
</script>
好了一个基本的element plus 表格二次封装就完成了