a
This commit is contained in:
163
COLUMN_VISIBILITY_SOLUTIONS.md
Normal file
163
COLUMN_VISIBILITY_SOLUTIONS.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# 列显示/隐藏方案对比
|
||||
|
||||
## 方案1:TableColumn 包装组件 ⭐推荐
|
||||
|
||||
### 优点
|
||||
- ✅ 使用简单,只需替换组件名
|
||||
- ✅ 完全兼容 `el-table-column` 的所有属性和插槽
|
||||
- ✅ 代码清晰,易于维护
|
||||
- ✅ 无需修改现有代码结构
|
||||
|
||||
### 缺点
|
||||
- ❌ 需要创建一个新组件
|
||||
- ❌ 需要在使用的地方 provide `isColumnVisible` 函数
|
||||
|
||||
### 使用示例
|
||||
|
||||
```vue
|
||||
<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
|
||||
- ❌ 可能不够优雅
|
||||
|
||||
### 使用示例
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<el-table>
|
||||
<el-table-column
|
||||
v-column-visible="'tied'"
|
||||
prop="tied"
|
||||
label="是否退休"
|
||||
width="100"
|
||||
/>
|
||||
</el-table>
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 方案3:使用 computed 动态生成列配置
|
||||
|
||||
### 优点
|
||||
- ✅ 最彻底,完全控制列的渲染
|
||||
- ✅ 性能最好(只渲染可见的列)
|
||||
|
||||
### 缺点
|
||||
- ❌ 需要重构现有代码,改动较大
|
||||
- ❌ 需要将列配置抽离出来
|
||||
- ❌ 插槽处理较复杂
|
||||
|
||||
### 使用示例
|
||||
|
||||
```vue
|
||||
<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 的渲染逻辑
|
||||
- ❌ 可能影响性能
|
||||
|
||||
---
|
||||
|
||||
## 推荐方案
|
||||
|
||||
**推荐使用方案1(TableColumn 包装组件)**,因为:
|
||||
1. 使用最简单,只需替换组件名
|
||||
2. 完全兼容现有代码
|
||||
3. 易于维护和理解
|
||||
4. 性能良好
|
||||
|
||||
## 迁移步骤(方案1)
|
||||
|
||||
1. 导入组件:
|
||||
```vue
|
||||
import TableColumnProvider from '/@/components/TableColumn/Provider.vue'
|
||||
import TableColumn from '/@/components/TableColumn/index.vue'
|
||||
```
|
||||
|
||||
2. 用 `TableColumnProvider` 包裹所有列,并传入 `isColumnVisible`:
|
||||
```vue
|
||||
<TableColumnProvider :is-column-visible="isColumnVisible">
|
||||
<!-- 所有列 -->
|
||||
</TableColumnProvider>
|
||||
```
|
||||
|
||||
3. 将所有 `el-table-column` 替换为 `TableColumn`,并移除 `v-if`:
|
||||
```vue
|
||||
<!-- 之前 -->
|
||||
<el-table-column v-if="isColumnVisible('tied')" prop="tied" label="是否退休" />
|
||||
|
||||
<!-- 之后 -->
|
||||
<TableColumn prop="tied" label="是否退休" />
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user