基于vxe-table进行二次封装

VxeTablePro 二次封装组件文档

一、实现目的

在企业级后台管理系统开发中,表格是最常用的组件之一,往往需要实现分页、搜索、排序、编辑、导出、全屏等通用功能。重复开发这些功能会导致效率低下且样式/逻辑不统一。基于此,VxeTablePro 组件的封装主要目标如下:

  1. 功能聚合:整合表格常用功能(分页、搜索、排序、编辑、导出、全屏等),减少重复开发
  2. 统一规范:统一表格样式、交互逻辑和接口设计,提升系统一致性
  3. 简化使用:通过配置化方式快速生成表格,降低开发门槛
  4. 可扩展性:支持自定义插槽、事件和配置,满足个性化需求
  5. 类型安全:基于 TypeScript 开发,提供完整类型定义,减少运行时错误

二、实现方式

1. 组件结构设计

采用主组件+子组件+hooks的分层架构,实现关注点分离:

bash 复制代码
VxeTablePro/
├── index.vue          # 主组件(整合所有功能)
├── components/        # 子组件
│   ├── Toolbar/index.vue    # 工具栏(新增、导出、全屏等按钮)
│   ├── SearchForm/index.vue # 搜索表单
│   ├── Modal/index.vue      # 提示弹窗
│   └── ElmentSlots/index.vue # 动态组件渲染
├── hooks/
│   └── useTable.ts    # 表格核心逻辑(数据请求、分页、排序等)
├── types.ts           # 类型定义
└── index.scss         # 样式文件

2. 核心逻辑封装

(1)数据处理层(useTable.ts)

采用组合式 API 封装表格核心逻辑,实现数据与视图分离:

  • 数据请求:统一处理接口调用、加载状态和错误捕获
  • 分页管理:封装 pageNo、pageSize、total 等分页参数及切换逻辑
  • 搜索与重置:处理查询参数的更新与重置
  • 排序逻辑:支持后端排序,转换排序参数格式
typescript 复制代码
// 核心逻辑示例(useTable.ts)
export const useTable = (api, initParam, isPageable = true) => {
  const state = reactive({
    tableData: [],
    pageable: { pageNo: 1, pageSize: 10, total: 0 },
    loading: false,
    searchParam: {}
  })

  // 获取表格数据
  const getTableList = async () => {
    state.loading = true
    try {
      const params = { ...state.searchParam, ...state.pageable }
      const data = await api(params)
      state.tableData = data.list
      state.pageable.total = data.total
    } finally {
      state.loading = false
    }
  }

  // 分页切换
  const handleSizeChange = (size) => {
    state.pageable.pageSize = size
    getTableList()
  }

  return { ...toRefs(state), getTableList, handleSizeChange }
}
(2)视图组件层(index.vue)

主组件负责整合所有功能模块,通过 props 接收配置,通过插槽提供扩展能力:

  • 表格渲染:基于 vxe-table 实现核心表格展示
  • 功能整合:集成搜索表单、工具栏、分页组件
  • 事件分发:统一处理编辑、删除、排序等事件
vue 复制代码
<!-- 核心结构示例(index.vue) -->
<template>
  <div class="vxe-commn-container-pro">
    <!-- 搜索表单 -->
    <SearchForm 
      ref="searchForm" 
      :formOptions="formOptions" 
      @search="getTableList"
    />
    
    <!-- 工具栏 -->
    <Toolbar 
      :tableRef="tableRef" 
      :exportHandler="exportHandler"
    />
    
    <!-- 表格主体 -->
    <vxe-table
      ref="tableRef"
      :data="tableData"
      :loading="loading"
      @sort-change="sortChangeEvent"
    >
      <vxe-column 
        v-for="item in columns" 
        :key="item.field" 
        v-bind="item"
      />
      <!-- 操作列 -->
      <vxe-column title="操作">
        <template #default="{ row }">
          <slot name="actionBtnSlot" :row="row" />
        </template>
      </vxe-column>
    </vxe-table>
    
    <!-- 分页 -->
    <VxePagination
      v-model:page="pageable.pageNo"
      v-model:limit="pageable.pageSize"
      :total="pageable.total"
    />
  </div>
</template>
(3)功能组件层
  • Toolbar:封装新增、导出、全屏、列设置等操作按钮,通过 props 控制按钮权限
  • SearchForm:基于 vxe-form 实现搜索表单,支持多种表单类型
  • Modal:统一提示弹窗,处理确认/取消逻辑

3. 扩展性设计

  • 插槽机制:支持自定义操作按钮(actionBtnSlot)、表头内容、搜索项等
  • 配置化:通过 columns 配置表格列属性,通过 props 控制功能开关(如 showToolbar、pagination)
  • 事件回调:暴露 editSuccess、deleteRow 等事件,允许自定义业务逻辑

三、产出价值

  1. 开发效率提升:平均减少 60% 以上的表格相关代码量,一个标准表格页面可在 10 分钟内完成开发
  2. 维护成本降低:核心逻辑集中维护,修改一处即可影响所有使用该组件的页面
  3. 用户体验统一:统一的交互方式(如排序、导出、编辑)降低用户学习成本
  4. 功能完整性:内置常用功能,无需重复开发,避免功能遗漏
  5. 类型安全保障:完整的 TypeScript 类型定义,减少 30% 以上的类型相关错误

四、使用方式

1. 基础用法

vue 复制代码
<template>
  <VxeTablePro
    :columns="columns"
    :requestApi="fetchTableData"
    :formOptions="formOptions"
  />
</template>

<script setup lang="ts">
import VxeTablePro from './VxeTablePro'
import { fetchTableData } from '@/api/table'

// 表格列配置
const columns = [
  { field: 'name', title: '名称', sortable: true },
  { field: 'date', title: '日期', showType: 'time' },
  { field: 'status', title: '状态', enum: statusEnum }
]

// 搜索表单配置
const formOptions = {
  fields: [
    { field: 'name', title: '名称', el: 'input' },
    { field: 'status', title: '状态', el: 'select', elProps: { options: statusEnum } }
  ]
}
</script>

2. 核心配置项

参数 类型 说明
columns ColumnProps[] 表格列配置
requestApi (params) => Promise 数据请求接口
formOptions object 搜索表单配置
pagination boolean 是否显示分页
actionsPermi { del: boolean; edit: boolean } 操作按钮权限
showToolbar boolean 是否显示工具栏
exportApi (params) => Promise 导出接口

3. 自定义操作按钮

vue 复制代码
<VxeTablePro
  :columns="columns"
  :requestApi="fetchTableData"
>
  <template #actionBtnSlot="{ row }">
    <el-button @click="handleView(row)">查看</el-button>
    <el-button @click="handleEdit(row)">编辑</el-button>
  </template>
</VxeTablePro>

4. 事件处理

vue 复制代码
<VxeTablePro
  :columns="columns"
  :requestApi="fetchTableData"
  @editSuccess="handleEditSuccess"
  @deleteRow="handleDelete"
/>

<script setup>
const handleEditSuccess = (row) => {
  console.log('编辑成功', row)
}

const handleDelete = async (row) => {
  await deleteApi(row.id)
  // 重新加载数据
  tableRef.value.getTableList()
}
</script>

五、总结

VxeTablePro 组件通过合理的分层设计和功能封装,在保持灵活性的同时大幅提升了表格开发效率。其核心思想是抽取共性、暴露个性:将重复出现的分页、搜索、排序等逻辑封装为内置功能,同时通过配置和插槽支持个性化需求。

该组件适合中大型后台系统,能够有效解决表格功能散乱、维护困难的问题,为开发团队提供统一的表格解决方案。

六、资料

1、项目中真实使用场景

2、链接

这个代码仓库中的VxeTablePro文件夹就是这个组件的全部源码
gitee.com/li-haibo-19...

相关推荐
小时前端3 小时前
现代Web认证体系深度解析:从JWT原理到SSO架构设计
前端·面试
闭着眼睛学算法3 小时前
【双机位A卷】华为OD笔试之【模拟】双机位A-新学校选址【Py/Java/C++/C/JS/Go六种语言】【欧弟算法】全网注释最详细分类最全的华子OD真题题解
java·c语言·javascript·c++·python·算法·华为od
前端一课4 小时前
公开分享一个AI番茄短故事模块技术方案(含代码)
前端
晴殇i4 小时前
为什么现代 JavaScript 代码规范开始建议禁止使用 else ?
前端·javascript·前端框架
梦6504 小时前
axios请求
vue.js
源力祁老师4 小时前
OWL与VUE3 的高级组件通信全解析
前端·javascript·vue.js
花开月正圆4 小时前
遇见docker-compose
前端
护国神蛙4 小时前
自动翻译插件中的智能字符串切割方案
前端·javascript·babel
TechFrank4 小时前
浏览器云端写代码,远程开发 Next.js 应用的简易教程
前端