下面给你一个 可直接使用、可落地的《基于 Vue3 + Element Plus 实现可定制列的动态表格配置组件》 —— 包含:
✔ 完整代码(可直接复制运行)
✔ 组件拆分、设计思路
✔ 支持列显示/隐藏、顺序拖拽、宽度个性化设定
✔ 支持持久化到 localStorage
✔ 兼容 Element Plus 的 <el-table>
非常适合项目实际使用。
🚀 最终效果(你将实现)
- 用户点击 “列设置” 图标 → 弹出配置面板
- 用户可操作:
- 勾选列使其显示/隐藏
- 拖拽改变列顺序
- 设置列宽
- 点击保存 → 表格立即更新
- 列配置会 自动持久化(localStorage)
📦 一、主组件结构(TableWithColumnConfig.vue)
包含:
<el-table>- 列配置按钮
- 弹窗组件
<ColumnConfigDialog />
TableWithColumnConfig.vue
<script setup>
import { ref, computed, watch } from "vue";
import ColumnConfigDialog from "./ColumnConfigDialog.vue";
// 初始化列配置
const defaultColumns = [
{ prop: "name", label: "姓名", width: 120, visible: true },
{ prop: "age", label: "年龄", width: 80, visible: true },
{ prop: "job", label: "工作", width: 160, visible: true },
{ prop: "address", label: "地址", width: 240, visible: true },
];
// 持久化 KEY
const STORAGE_KEY = "column_config_demo";
// 从 localStorage 读取配置
function loadConfig() {
const saved = localStorage.getItem(STORAGE_KEY);
return saved ? JSON.parse(saved) : defaultColumns;
}
const columns = ref(loadConfig());
// 表格数据
const tableData = ref([
{ name: "张三", age: 25, job: "前端工程师", address: "北京" },
{ name: "李四", age: 30, job: "后端工程师", address: "上海" },
]);
// 控制弹窗
const dialogVisible = ref(false);
// 保存配置
function saveConfig(newConfig) {
columns.value = newConfig;
localStorage.setItem(STORAGE_KEY, JSON.stringify(newConfig));
}
</script>
<template>
<div>
<el-button type="primary" @click="dialogVisible = true">
列配置
</el-button>
<!-- 表格 -->
<el-table :data="tableData" border style="margin-top: 16px">
<el-table-column
v-for="col in columns"
v-if="col.visible"
:key="col.prop"
:prop="col.prop"
:label="col.label"
:width="col.width"
/>
</el-table>
<!-- 配置弹窗 -->
<ColumnConfigDialog
v-model="dialogVisible"
:columns="columns"
@save="saveConfig"
/>
</div>
</template>
📦 二、列配置弹窗组件(ColumnConfigDialog.vue)
支持:
- 显示/隐藏列
- 输入列宽
- 拖拽排序(使用 vuedraggable@next)
安装依赖(拖拽排序)
npm install vuedraggable@next
ColumnConfigDialog.vue
<script setup>
import { ref, watch, computed } from "vue";
import draggable from "vuedraggable";
import { ElMessage } from "element-plus";
const props = defineProps({
modelValue: Boolean,
columns: { type: Array, required: true },
});
const emits = defineEmits(["update:modelValue", "save"]);
// 本地临时配置(不直接修改父组件)
const localConfig = ref(JSON.parse(JSON.stringify(props.columns)));
watch(
() => props.modelValue,
(val) => {
if (val) {
localConfig.value = JSON.parse(JSON.stringify(props.columns));
}
}
);
// 保存
function handleSave() {
emits("save", localConfig.value);
emits("update:modelValue", false);
ElMessage.success("保存成功!");
}
function close() {
emits("update:modelValue", false);
}
</script>
<template>
<el-dialog
title="列配置"
:model-value="modelValue"
width="500px"
@close="close"
>
<draggable v-model="localConfig" item-key="prop">
<template #item="{ element }">
<el-row
style="padding: 6px; border-bottom: 1px solid #eee;"
align="middle"
>
<el-col :span="2">
<el-icon><Menu /></el-icon>
</el-col>
<el-col :span="6">
<el-checkbox v-model="element.visible">
{{ element.label }}
</el-checkbox>
</el-col>
<el-col :span="10">
<el-input-number
v-model="element.width"
:min="60"
:max="400"
size="small"
label="列宽"
/>
</el-col>
</el-row>
</template>
</draggable>
<template #footer>
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="handleSave">保存</el-button>
</template>
</el-dialog>
</template>
🧠 三、组件设计思路(简明讲解)
1. columns 数据结构每列包括:
{
prop: "name",
label: "姓名",
width: 120,
visible: true
}
2. 弹窗中使用 localConfig 本地副本
避免配置未保存前影响主表格。
3. vuedraggable 实现列顺序拖拽
拖拽后 localConfig 自动更新排序。
4. 保存配置 → 同步到父组件 + localStorage
保持下次进入仍然生效。
🧩 四、可扩展能力(直接可加)
我可以帮你继续扩展成更完整的版本,包括:
- ✔ 列分组(多级表头)配置
- ✔ 列固定(fixed left / right)
- ✔ 列排序(sorter)
- ✔ 列过滤器配置
- ✔ 一键恢复默认配置
- ✔ 将配置同步到数据库(用户级别)
发表回复