下面给你一个 可直接使用、可落地的《基于 Vue3 + Element Plus 实现可定制列的动态表格配置组件》 —— 包含:

✔ 完整代码(可直接复制运行)
✔ 组件拆分、设计思路
✔ 支持列显示/隐藏、顺序拖拽、宽度个性化设定
✔ 支持持久化到 localStorage
✔ 兼容 Element Plus 的 <el-table>

非常适合项目实际使用。


🚀 最终效果(你将实现)

  • 用户点击 “列设置” 图标 → 弹出配置面板
  • 用户可操作:
    • 勾选列使其显示/隐藏
    • 拖拽改变列顺序
    • 设置列宽
  • 点击保存 → 表格立即更新
  • 列配置会 自动持久化(localStorage)

📦 一、主组件结构(TableWithColumnConfig.vue)

包含:

  • <el-table>
  • 列配置按钮
  • 弹窗组件 <ColumnConfigDialog />

TableWithColumnConfig.vue

&lt;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));
}
&lt;/script>

&lt;template>
  &lt;div>
    &lt;el-button type="primary" @click="dialogVisible = true">
      列配置
    &lt;/el-button>

    &lt;!-- 表格 -->
    &lt;el-table :data="tableData" border style="margin-top: 16px">
      &lt;el-table-column
        v-for="col in columns"
        v-if="col.visible"
        :key="col.prop"
        :prop="col.prop"
        :label="col.label"
        :width="col.width"
      />
    &lt;/el-table>

    &lt;!-- 配置弹窗 -->
    &lt;ColumnConfigDialog
      v-model="dialogVisible"
      :columns="columns"
      @save="saveConfig"
    />
  &lt;/div>
&lt;/template>


📦 二、列配置弹窗组件(ColumnConfigDialog.vue)

支持:

  • 显示/隐藏列
  • 输入列宽
  • 拖拽排序(使用 vuedraggable@next)

安装依赖(拖拽排序)

npm install vuedraggable@next


ColumnConfigDialog.vue

&lt;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);
}
&lt;/script>

&lt;template>
  &lt;el-dialog
    title="列配置"
    :model-value="modelValue"
    width="500px"
    @close="close"
  >
    &lt;draggable v-model="localConfig" item-key="prop">
      &lt;template #item="{ element }">
        &lt;el-row
          style="padding: 6px; border-bottom: 1px solid #eee;"
          align="middle"
        >
          &lt;el-col :span="2">
            &lt;el-icon>&lt;Menu />&lt;/el-icon>
          &lt;/el-col>

          &lt;el-col :span="6">
            &lt;el-checkbox v-model="element.visible">
              {{ element.label }}
            &lt;/el-checkbox>
          &lt;/el-col>

          &lt;el-col :span="10">
            &lt;el-input-number
              v-model="element.width"
              :min="60"
              :max="400"
              size="small"
              label="列宽"
            />
          &lt;/el-col>
        &lt;/el-row>
      &lt;/template>
    &lt;/draggable>

    &lt;template #footer>
      &lt;el-button @click="close">取消&lt;/el-button>
      &lt;el-button type="primary" @click="handleSave">保存&lt;/el-button>
    &lt;/template>
  &lt;/el-dialog>
&lt;/template>


🧠 三、组件设计思路(简明讲解)

1. columns 数据结构每列包括:

{
  prop: "name",
  label: "姓名",
  width: 120,
  visible: true
}

2. 弹窗中使用 localConfig 本地副本

避免配置未保存前影响主表格。

3. vuedraggable 实现列顺序拖拽

拖拽后 localConfig 自动更新排序。

4. 保存配置 → 同步到父组件 + localStorage

保持下次进入仍然生效。


🧩 四、可扩展能力(直接可加)

我可以帮你继续扩展成更完整的版本,包括:

  • ✔ 列分组(多级表头)配置
  • ✔ 列固定(fixed left / right)
  • ✔ 列排序(sorter)
  • ✔ 列过滤器配置
  • ✔ 一键恢复默认配置
  • ✔ 将配置同步到数据库(用户级别)