从零开始vue3+vite+ts+pinia+router4后台管理(5)-二次封装表格1.0

1,141 阅读3分钟

从零开始vue3+vite+ts+pinia+router4后台管理(5)-二次封装表格1.0

项目地址

代码gitee地址

在线预览

思路和原则

二次封装UI组件要注意的三个地方分别是属性、事件、插槽,我们在封装组件的时候,无非是往这个方向,我们在封装的时候不能影响 原UI组件原有的属性、事件,插槽的前提下,然后在其基础上做二次封装,这是一个必须的原则,如果影响了原来的UI组件那就不是一个好的封装

页面可以分为4个模块

image-20231012145926255

  1. 表格搜索区域
  2. 表格数据操作按钮区域
  3. 表格主体内容展示区域
  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 默认是英文显示

默认的分页样式

image-20231012151101182

要改成中文需要在入口文件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 表格二次封装就完成了