Vue.js管理后台Table组件封装实战:从全局注册到多场景渲染

作者:组件花园时间:2026-10-24 13:59:07浏览:325

本文详细介绍如何在Vue.js项目中封装通用的Table组件,旨在简化后台管理系统的开发流程。通过定义统一的数据结构,支持普通数据展示、自定义插槽以及多种按钮操作场景。文章涵盖组件的全局注册方法、handleFilter数据处理逻辑及分页组件的集成,帮助开发者实现高效、可复用的表格组件。

近期启动新项目,本文简要分享Table组件的封装思路与实践。

问题分析

封装的必要性

封装并非单纯为了追求技术高度,更多是出于提升效率的考量。为了避免在创建新表格时重复粘贴复制代码,通过封装Table组件,开发者只需填充数据即可快速生成表格,从而减少冗余工作。

封装范围

本次封装主要包含两个部分:核心的Table组件以及配套的分页组件。

明确上述目标后,即可着手进行组件的封装工作。

Table组件封装步骤

确定数据结构

首先需明确数据格式,参考Element UI的el-table组件规范进行定义。


<el-table :data="tableData" style="width: 100%">
   <el-table-column prop="date" label="日期" width="180" />
   <el-table-column fixed="right" label="操作" width="100">
      <template slot-scope="scope">
        <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
        <el-button type="text" size="small">编辑</el-button>
     </template>
   </el-table-column>
</el-table>

接下来考虑数据类型,包括label、prop、width、按钮类型及事件处理等字段。


let paramsType = {
  data: Array, // 数据
  loading: Boolean,
  selectionShow: Boolean,
  columns:Array = [
    { 
      label: String,
      prop: String,
      filter: Function,
      isSlot: Boolean,
      width: Number,
      tempalte: Function,
      btns: Array = [
        { name: String,
          btnType: String,
          clickType: String,
          routerType: String,
          url: String,
          query: Function,
          btnClick: Function
        }
      ]
    }
  ] 
}

定义好数据文档后,即可开始具体的组件封装工作。

组件封装实施

全局组件注册

将组件封装为全局组件的主要目的是简化调用流程,核心目标依然是提高开发效率。

在src目录下创建components文件夹,将组件放入其中。建议每个组件单独占用一个文件夹,以便于后续维护。

创建名为FrTable的table.vue组件,具体实现细节稍后说明,先介绍引用方式。

全局使用配置

将FrTable文件导入到components目录下的index.js中,遍历所有组件并统一导出。

相关代码如下:


import TrTable from './FrTable/index'

const components = [TrTable]

const install = (Vue) => {
  components.map(component => {
    Vue.component(component.name, component)
  })
}

if (typeof Window !== 'undefined' && window.Vue) {
  install(Window.Vue)
}

export default {
  install
}

随后在main.js中将组件导出,并通过Vue.use()方法注册使用,具体操作如下:


import globalComponents from '@/components/index'
Vue.use(globalComponents)

页面中的具体应用


<fr-table />

Table组件封装细节

需考虑的问题

Table组件需要覆盖哪些场景?

  • 正常的数据类型展示
  • 独特的展示方式
  • 包含操作按钮的情况

对于第一种情况,无需过多操作,只需通过for循环进行渲染即可。

第二种情况相对简单,可以通过slot进行定制化处理。

第三种情况涉及按钮操作,按钮类型可细分为多种。

按钮类型分类

  1. 按钮的正常使用,即点击触发功能
  2. 按钮用于页面跳转
  3. 按钮用于打开新页面
  4. 按钮用于触发自定义事件

代码编写

基于上述分析,已明确Table的所有问题点,接下来只需编写代码即可。

第一种场景处理


<el-table :data="data" border :loading="loading">
        <!-- 勾选 -->
   <el-table-column v-if="selectionShow" type="selection" width="50" align="center" :reserve-selection="true" />
     <template v-for="(item, index) in columns">
        <el-table-column :key="index" v-bind="item">
            <!-- 自定义表头 -->
          <template v-if="item.customHeader" slot="header">
              <slot :name="item.headerProp" />
          </template>
          <template slot-scope="scope">
               <span v-html="handleFilter(item, scope.row, item.prop)" />
          </template>
        </el-table-column>
     </template>
 </el-table>

此处可以看到handleFilter方法。

该方法用于处理数据。

数据类型分为正常数据类型、需转化的数据类型以及模板转化的数据类型。

相关代码如下:


handleFilter(item, val, prop) {
  let value = val[prop]
  if (item.templet) value = item.templet(val)
  return item.filter ? this.$options.filters[item.filter](val[prop]) : value
},

第一种情况较为简单,仅涉及基础数据渲染和定制化表头渲染。上述示例主要展示了多选功能结合普通表单的场景。

第二种场景处理

自定义列表展示


<template slot-scope="scope">
   <!-- 自定义内容 -->
   <slot
      v-if="item.isSlot"
      :name="item.prop"
      :row="scope.row"/
   >
</template>

对于自定义类别,只需将isSlot设置为true,并指定name为prop,row为data即可。

第三种场景处理

第三种场景下的按钮分为四种类型。


<template v-if="item.btns">
   <el-button
     v-for="(btn, i) in item.btns"
     :key="i"
    class="mr_10"
    :size="btn.mini ? btn.mini: 'small'"
    :type="btn.type ? btn.type: 'primary'"
    @click="btnClickfunc(btn, scope.row)"
  >
     {{ btn.name }}
  </el-button>
</template>

按钮依然通过循环渲染,主要区别在于事件分析,通过btnClickfunc事件进行操作。


btnClickfunc(column, row) {
      const path = {
        [column.routerType]: column.url,
        query: column.query ? column.query(row) : ''
      }
      if (column.clickType === 'router') {
        this.$router.push(path)
      } else if (column.clickType === 'router_blank') {
        const routeData = this.$router.resolve(path)
        window.open(routeData.href, '_blank')
      } else if (column.clickType === 'btnClick') {
        column.btnClick(row)
      } else {
        this.$emit('btnClickFunc', { column: column, row: row })
      }
},

针对不同类别,执行不同的处理逻辑。

Props传参值

当前参数与定义的参数保持一致,因此代码如下:


  // 数据
    data: {
      type: Array,
      required: true
    },
    // 表头参数
    columns: {
      type: Array,
      required: true
    },
    loading: {
      type: Boolean,
      default: false
    },
    // 多选框选择
    selectionShow: {
      type: Boolean,
      default: false
    },

至此,仅剩下组件的使用方式需要说明。

组件使用示例


<fr-table
      ref="mt"
      :loading="loading"
      :data="list"
      :columns="columns"
    >
</fr-table>

大致结构如下,若需使用多选功能,可自行定义方法;排序功能同理。

分页组件封装

参考Element UI的分页组件进行设计。


<el-pagination
  style="margin-top:40px;"
  background
  layout="prev, pager, next"
  :page-size="pageLimit"
   :total="total"
   :current-page="currentPage"
   @current-change="handleCurrentChange"
/>
handleCurrentChange(val) {
   console.log(val)
}

数据定义

定义如下:


total: Number,
pageLimit: Number,
currentPage: Number,

封装实现


<el-pagination
  style="margin-top:40px;"
  background
  layout="prev, pager, next"
  :page-size="pageLimit"
  :total="total"
  :current-page="currentPage"
  @current-change="handleCurrentChange"
/>

handleCurrentChange(val) {
   this.$emit('currentChange', val)
}

看起来是否很简单?实际上实现过程确实如此简洁。

随后在组件上添加分页事件和参数,整个Table组件的封装工作即告完成。

总结

至此,关于Vue.js管理后台Table组件封装的文章介绍完毕。更多相关Vue后台Table封装内容,请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

作者最新文章