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>