vue3自定义表格生成动态列

javascript 复制代码
<template>
  <div>
    <el-table :data="tableData" style="width: 100%">
      <!-- 动态生成表头和列 -->
      <el-table-column v-for="column in columns" :key="column.prop" :label="column.label" :prop="column.prop">
        <template v-slot:default="scope">
          <component :is="renderCell(column, scope.row)" />
        </template>
      </el-table-column>
    </el-table>
    <el-button @click="toggleEdit">{{ isEditing ? '保存' : '编辑' }}</el-button>
  </div>
</template>

<script setup>
import { ref, reactive, h } from 'vue';

// 模拟从后端获取的数据
const backendData = {
  columns: [
    { label: '姓名', prop: 'name', editable: true, type: 'input' },
    { label: '年龄', prop: 'age', editable: true, type: 'input' },
    { label: '性别', prop: 'gender', editable: true, type: 'select' },
    { label: '入职日期', prop: 'hireDate', editable: false, type: 'date' }
  ],
  data: [
    { name: '张三', age: 28, gender: '男', hireDate: '2023-01-01' },
    { name: '李四', age: 35, gender: '女', hireDate: '2023-02-15' }
  ]
};

// 表头数据
const columns = ref(backendData.columns);

// 表格数据
const tableData = ref([...backendData.data]);

// 是否处于编辑状态
const isEditing = ref(false);

// 切换编辑状态
const toggleEdit = () => {
  if (isEditing.value) {
    // 保存操作
    console.log('保存数据:', tableData.value);
  }
  isEditing.value = !isEditing.value;
};

// 根据列类型和行数据生成渲染函数
const renderCell = (column, row) => {
  return () => {
    const value = row[column.prop];
    if (!column.editable || !isEditing.value) {
      return h('span', {}, value);
    }

    switch (column.type) {
      case 'input':
        return h(
          'el-input',
          {
            modelValue: value,
            'onUpdate:modelValue': (newValue) => {
              row[column.prop] = newValue;
            },
            onBlur: () => handleBlur(row, column.prop),
            onChange: (event) => handleChange(row, column.prop, event)
          }
        );
      case 'select':
        return h(
          'el-select',
          {
            modelValue: value,
            'onUpdate:modelValue': (newValue) => {
              row[column.prop] = newValue;
            },
            onChange: (event) => handleChange(row, column.prop, event)
          },
          getOptions(column.prop).map(option =>
            h('el-option', { key: option.value, label: option.label, value: option.value })
          )
        );
      case 'date':
        return h(
          'el-date-picker',
          {
            modelValue: value,
            'onUpdate:modelValue': (newValue) => {
              row[column.prop] = newValue;
            },
            onChange: (event) => handleChange(row, column.prop, event)
          }
        );
      default:
        return h('span', {}, value);
    }
  };
};

// 获取选项数据(仅用于 select 类型)
const getOptions = (prop) => {
  if (prop === 'gender') {
    return [
      { value: '男', label: '男' },
      { value: '女', label: '女' }
    ];
  }
  return [];
};

// 处理输入框失去焦点事件
const handleBlur = (row, prop) => {
  console.log(`第 ${tableData.value.indexOf(row) + 1} 行的 ${prop} 字段失去焦点`);
};

// 处理选择器值变化事件
const handleChange = (row, prop, value) => {
  console.log(`第 ${tableData.value.indexOf(row) + 1} 行的 ${prop} 字段值变为 ${value}`);
};
</script>

<style scoped>
/* 添加一些样式以美化表格 */
.el-table {
  margin-bottom: 20px;
}
</style>
相关推荐
CharlesYu018 小时前
前端性能优化的第一性原理,是不断缩短“用户发起意图 → 获得可用结果”之间的时间
前端
Bs_MoneyMagnet8 小时前
基于springboot+vue的医疗健康便民服务平台的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring
平头哥技术团队9 小时前
Day 21 _ 页内锚点_给每段起个 id,目录写 href=_#id_,点一下页面就滚到那一段
前端·html·html5
子兮曰10 小时前
Bun v1.4.1 深度解析:从 Zig 到 Rust,一场 11 天、64 个 AI 代理的语言迁徙
前端·后端·bun
人民广场吃泡面10 小时前
什么是AI Agent?它又能给前端带来哪些效率提升?
前端·人工智能
中科三方10 小时前
两家域名注册商资质被ICANN终止:企业域名资产安全再受关注
前端·网络·安全·域名
bug总结11 小时前
uniapp vue3全局方法注册使用
前端·javascript·uni-app
华无丽言11 小时前
如何在宜搭中实现获取子表中的字段值赋值到父表中?
前端·javascript·低代码
IT_陈寒12 小时前
Vue的computed属性竟然坑了我一把
前端·人工智能·后端
威斯软科的老司机12 小时前
通俗讲解 CNN 图像识别、向量 Embedding、Softmax 概率计算这三块的简化原理
前端·人工智能·ui·数字孪生