Vue 3 + Element Plus 实现可定制的动态表格列配置组件

1,082 阅读5分钟

引言

在现代后台管理系统中,表格作为数据展示的核心组件,其灵活性和可配置性直接影响用户体验。传统的静态表格列配置已经无法满足不同用户、不同场景下的个性化需求。本文将介绍我们最新开发的智能表格列配置系统,它基于 Vue 3 和 Element Plus 构建,提供了完整的列配置解决方案。

功能概述

我们实现的自定义列功能包含以下特点:

  1. 可视化配置:通过界面直接配置表格列的显示、顺序、宽度等属性
  2. 多Tab支持:一个页面可以配置多个表格Tab,每个Tab有独立的列配置
  3. 表头提示:支持在表头添加提示信息
  4. 特殊列处理:支持通过插槽对特定列进行特殊渲染
  5. 持久化存储:所有配置保存到后端,不同用户可保存不同配置

技术栈

  • Vue3
  • Element Plus
  • vuedraggable (用于实现拖拽排序)

核心组件实现

1. 动态表格列组件 (CustomizeTableColumns)

<template>
  <!-- 动态列 -->
  <el-table-column
    :prop="column.prop"
    :label="column.label"
    :align="column.align || 'center'"
    :width="column.width"
    :min-width="column.minWidth"
    :fixed="column.fixed"
    :sortable="column.sortable"
    :formatter="column.formatter ? dateFormatter : null"
    show-overflow-tooltip
  >
    <!-- 统一表头模板 -->
    <template #header>
      <template v-if="column.headEdit?.toolTipTitle">
        <span>{{ column.label }}</span>
        <el-tooltip :content="column.headEdit?.toolTipTitle">
          <Icon
            class="header-icon ml-1"
            :color="column.headEdit?.iconColor || 'orange'"
            :icon="column.headEdit?.iconComponent || 'ep:info-filled'"
          />
        </el-tooltip>
      </template>
      <template v-if="column.slotEdit">
        <div class="flex justify-center items-center cursor-pointer">
          <span>{{ column.label }}</span>
          <el-tooltip content="自定义修改表头配置" placement="top" v-hasPermi="['infra:tableColumns:update']">
            <el-button type="success" text @click="handleOpenConfig">
              <Icon icon="ep:setting" :size="16" />
            </el-button>
          </el-tooltip>
        </div>
      </template>
    </template>
    <!-- 自定义列模板 针对特殊列通过插槽进行特殊处理 -->
    <template #default="scope" v-if="column.slot">
      <slot name="column-cell" :column="column" :row="scope.row" :index="scope.$index"></slot>
    </template>
  </el-table-column>
</template>

<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'

const props = defineProps({
  column: {
    type: Object,
    required: true
  }
})

const emit = defineEmits(['open:config'])

const handleOpenConfig = () => {
  emit('open:config', true)
}
</script>

<!-- interface ColumnConfig {
  prop: string // 字段名
  label: string // 显示名称
  width?: number // 列宽
  minWidth?: number // 最小宽度
  align?: 'left' | 'center' | 'right' // 对齐方式
  fixed?: 'left' | 'right' // 固定位置
  sortable?: boolean // 是否可排序
  visible: boolean // 是否显示
  order: number // 排序序号
  slot?: boolean // 是否使用插槽
  headEdit?: {
    toolTipTitle: string // 文字提示内容
    iconComponent?: Component // 直接传递组件
    iconColor?: string // 图标颜色
  },
  slotEdit: boolean, // 用户自定义列按钮,只能在一个列旁边展示且该列用户不允许进行隐藏操作
  formatter?: boolean // 是否需要格式化
  showAdvanced?: boolean // 是否显示高级设置
} -->

功能特点

这个组件接收一个 column 属性,根据配置渲染不同的表格列。主要功能包括:

  • 基础列属性:prop、label、width、align等
  • 表头提示:通过 toolTipTitle 配置提示信息
  • 配置按钮:通过 slotEdit 控制是否显示配置按钮
  • 自定义内容:通过 slot 插槽支持特殊列的自定义渲染

2. 列配置对话框 (ColumnConfigDialog)

<template>
  <el-dialog
    v-model="showDialog"
    title="表格列配置"
    width="800px"
    append-to-body
    class="column-config-dialog"
  >
    <!-- 对话框内容 -->
    <div class="operation-bar">
      <el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" class="mr-4">
        全选
      </el-checkbox>
      <el-button type="text" size="small" @click="toggleAdvancedSettings">
        {{ showAdvancedSettings ? '隐藏高级设置' : '显示高级设置' }}
      </el-button>
      <el-button type="text" size="small" @click="resetToDefault">重置默认</el-button>
    </div>
    
    <!-- 列配置列表 -->
    <draggable
      v-model="tempColumns"
      item-key="prop"
      handle=".drag-handle"
      ghost-class="ghost"
      chosen-class="chosen"
      animation="200"
    >
      <!-- 列配置项 -->
    </draggable>
  </el-dialog>
</template>

核心功能

  1. 列可见性控制:支持单个列显示/隐藏和全选操作
  2. 拖拽排序:使用 vuedraggable 实现灵活的列顺序调整
  3. 分组配置:支持基础配置和高级配置的分组管理
  4. 重置功能:一键恢复默认配置
  5. 表头编辑:支持表头提示信息的自定义

3. 列配置管理面板 (ColumnConfigPanel)

<template>
  <div class="column-config-panel">
    <el-table :data="columns" row-key="prop" border size="small">
      <el-table-column prop="label" label="列名" width="200">
        <template #default="{ row }">
          <el-input v-model="row.label" size="small" />
        </template>
      </el-table-column>
      
      <!-- 其他配置项 -->
    </el-table>
    
    <!-- 保存按钮 -->
    <div class="save-footer">
      <el-button type="primary" @click="saveConfig">保存配置</el-button>
    </div>
  </div>
</template>

功能亮点

  • 表格化配置界面,直观易用
  • 支持批量编辑列属性
  • 提供配置验证功能
  • 支持与后端 API 交互保存配置

关键技术实现

1. 动态列渲染机制

const dynamicColumns = computed(() => {
  return columnOptions.value
    .filter(col => col.visible)
    .sort((a, b) => a.order - b.order)
})

2. 列配置数据结构

interface ColumnConfig {
  prop: string // 字段名
  label: string // 显示名称
  width?: number // 列宽
  minWidth?: number // 最小宽度
  align?: 'left' | 'center' | 'right' // 对齐方式
  fixed?: 'left' | 'right' // 固定位置
  sortable?: boolean // 是否可排序
  visible: boolean // 是否显示
  order: number // 排序序号
  slot?: boolean // 是否使用插槽
  headEdit?: {
    toolTipTitle: string // 提示文字
    iconComponent?: string // 图标组件
    iconColor?: string // 图标颜色
  }
  slotEdit: boolean // 是否显示配置按钮
  formatter?: boolean // 是否需要格式化
  showAdvanced?: boolean // 是否显示高级设置
}

3. 配置持久化方案

const saveConfig = async () => {
  const tableConfigurationReqVOs = adaptFrontendToBackendColumns(columns.value)
  const params = {
    tabMenuId: props.tabId,
    moduleId: props.moduleId,
    menuId: props.menuId,
    tableConfigurationReqVOs
  }

  await customizeColumnConfig(params)
  message.success('配置保存成功')
}

最佳实践

1. 性能优化建议

  1. 虚拟滚动:对于大数据量表格,使用虚拟滚动提升性能
  2. 按需加载:只在需要时加载列配置对话框
  3. 防抖处理:对频繁操作如宽度调整添加防抖

2. 用户体验优化

  1. 配置预览:在保存前提供配置预览功能
  2. 快捷键支持:添加常用操作的快捷键
  3. 操作引导:首次使用时显示操作引导

3. 错误处理策略

  1. 配置验证:保存前验证配置合法性
  2. 错误回退:配置加载失败时使用默认配置
  3. 错误提示:友好的错误提示信息

实际应用案例

1. 多 Tab 表格配置

<template>
  <el-tabs v-model="activeName" @tab-click="handleTabClick">
    <el-tab-pane v-for="tab in tableTabListData" :key="tab.moduleId" 
      :label="tab.tabName" :name="tab.moduleId" />
  </el-tabs>

  <el-table :data="list">
    <CustomizeTableColumns v-for="col in dynamicColumns" :key="col.prop" :column="col">
      <template #column-cell="{ column, row }">
        <!-- 自定义列内容 -->
      </template>
    </CustomizeTableColumns>
  </el-table>
</template>

2. 复杂列内容渲染

<template #column-cell="{ column, row }">
  <template v-if="column.prop === 'status'">
    <el-tag :type="getStatusTagType(row.status)">
      {{ getStatusText(row.status) }}
    </el-tag>
  </template>
  
  <template v-else-if="column.prop === 'operation'">
    <el-button @click="handleEdit(row)">编辑</el-button>
    <el-button @click="handleDelete(row)">删除</el-button>
  </template>
</template>

效果展示

410a04a0-b5cb-46b7-aebe-acfe87946850.png

8e6aeb6b-c1d1-41a1-9bae-d6283cb84ef9.png

image.png

350de0b4-c6b2-4b79-8976-7619653cb0d7.png

总结

本文详细介绍了一个基于 Vue 3 和 Element Plus 的智能表格列配置系统的完整实现方案。该系统具有以下特点:

  1. 高度可配置:支持列显示、排序、宽度、对齐等全方位配置
  2. 用户友好:直观的配置界面和操作流程
  3. 灵活扩展:易于添加新的配置项和功能
  4. 前后端分离:清晰的 API 设计,便于与后端集成

通过这套系统,我们可以为不同用户提供个性化的表格视图,显著提升了后台管理系统的用户体验和操作效率。开发者可以根据实际需求,进一步扩展功能,如添加列分组、条件样式等高级特性。