Files
school-developer/COLUMN_VISIBILITY_SOLUTIONS.md
guochunsi 9e583c3c30 a
2026-01-06 16:39:57 +08:00

3.8 KiB
Raw Blame History

列显示/隐藏方案对比

方案1TableColumn 包装组件 推荐

优点

  • 使用简单,只需替换组件名
  • 完全兼容 el-table-column 的所有属性和插槽
  • 代码清晰,易于维护
  • 无需修改现有代码结构

缺点

  • 需要创建一个新组件
  • 需要在使用的地方 provide isColumnVisible 函数

使用示例

<template>
  <el-table ref="tableRef">
    <TableColumnProvider :is-column-visible="isColumnVisible">
      <!-- 替换 el-table-column  TableColumn移除 v-if -->
      <TableColumn prop="tied" label="是否退休" width="100" align="center">
        <template #default="scope">
          <StatusTag :value="scope.row.tied" :options="YES_OR_NO" />
        </template>
      </TableColumn>
      
      <TableColumn prop="nameNo" label="姓名/工号" min-width="150" align="center" fixed>
        <template #default="scope">
          <TeacherNameNo :name="scope.row.realName" :no="scope.row.teacherNo" />
        </template>
      </TableColumn>
    </TableColumnProvider>
  </el-table>
</template>

<script setup>
import TableColumnProvider from '/@/components/TableColumn/Provider.vue'
import TableColumn from '/@/components/TableColumn/index.vue'

const isColumnVisible = (propOrLabel) => {
  return tableColumnControlRef.value?.isColumnVisible?.(propOrLabel) ?? true
}
</script>

方案2自定义指令 v-column-visible

优点

  • 可以保留 el-table-column
  • 使用相对简单

缺点

  • 仍然需要在每个列上添加指令
  • 实现较复杂,需要操作 DOM
  • 可能不够优雅

使用示例

<template>
  <el-table>
    <el-table-column 
      v-column-visible="'tied'"
      prop="tied" 
      label="是否退休" 
      width="100" 
    />
  </el-table>
</template>

方案3使用 computed 动态生成列配置

优点

  • 最彻底,完全控制列的渲染
  • 性能最好(只渲染可见的列)

缺点

  • 需要重构现有代码,改动较大
  • 需要将列配置抽离出来
  • 插槽处理较复杂

使用示例

<template>
  <el-table>
    <component 
      v-for="col in visibleColumns" 
      :is="col.component" 
      v-bind="col.props"
    >
      <template v-if="col.slots" #[slotName]="slotProps" v-for="(slot, slotName) in col.slots">
        <component :is="slot" v-bind="slotProps" />
      </template>
    </component>
  </el-table>
</template>

<script setup>
const columns = [
  { prop: 'tied', label: '是否退休', component: 'el-table-column', slots: { default: StatusTag } },
  // ...
]

const visibleColumns = computed(() => {
  return columns.filter(col => isColumnVisible(col.prop || col.label))
})
</script>

方案4在 el-table 层面使用 provide + 自动处理

优点

  • 在表格层面统一处理
  • 子组件自动继承

缺点

  • 实现最复杂
  • 需要修改 Element Plus 的渲染逻辑
  • 可能影响性能

推荐方案

推荐使用方案1TableColumn 包装组件),因为:

  1. 使用最简单,只需替换组件名
  2. 完全兼容现有代码
  3. 易于维护和理解
  4. 性能良好

迁移步骤方案1

  1. 导入组件:
import TableColumnProvider from '/@/components/TableColumn/Provider.vue'
import TableColumn from '/@/components/TableColumn/index.vue'
  1. TableColumnProvider 包裹所有列,并传入 isColumnVisible
<TableColumnProvider :is-column-visible="isColumnVisible">
  <!-- 所有列 -->
</TableColumnProvider>
  1. 将所有 el-table-column 替换为 TableColumn,并移除 v-if
<!-- 之前 -->
<el-table-column v-if="isColumnVisible('tied')" prop="tied" label="是否退休" />

<!-- 之后 -->
<TableColumn prop="tied" label="是否退休" />