前景提要。用户需要一个可编辑table。并且实现动态增减默认回显一行。会根据选择的Type是什么类型来显示编辑的input的类型。
先缕清逻辑:
1.默认回显一行。而且已知前端的table需要唯一值id。如果设置index为id那么动态增减会出现问题(增减的时候控制Index会重复)。可以用动态生成唯一Id。我这里用到的是nanoid。然后动态增减用数组splice方法
<el-table :border="true" ref="tableBox" :data="ruleForm.tableData">
<!-- 动态增减 -->
<el-table-column min-width="20" label="" align="">
<template slot-scope="scope">
<div style="font-size: 20px">
<i
class="el-icon-remove"
v-if="tableData.length > 1"
@click="clinkTableBtn('del', scope.row)"
></i>
<i
class="el-icon-circle-plus"
@click="clinkTableBtn('add', scope.row)"
></i>
</div>
</template>
</el-table-column>
</el-table>
data() {
//默认回显的第一行数据
tableData:[
{
type: "",
value: "",
id: generateNanoId(),
},
],
rules: {
field: [
{ required: true, message: "请选择类型", trigger: "blur" },
]
}
}
methods: {
//table动态增减
clinkTableBtn(type, row) {
const index = this.tableData.findIndex((item) => item.id == row.id);
if (type === "add") {
let addData = {
type: "and",
value: "",
id: generateNanoId(),
};
this.tableData.splice(index + 1, 0, addData);
} else if (type === "del") {
this.tableData.splice(index, 1);
}
},
}
2.重点是根据type类型来动态回显当前行编辑的类型。我们的type的格式大概是[{name:“city”,type:“string”,options:[]}]。首先根据这个数组来渲染slect的options选项v-for就行。然后此时option的value我选的是整个数组。这样方便后面回显类型。然后数组中type的enum是string,number,datatime。如果options.length>0则string和input变成select。里面的内容就是options的内容。
3.避免你编辑一格其他会同时编辑也就是要保证当前的编辑name唯一。用到了slot-scope=“scope”
4.table中某些编辑列必传。以及table表头显示小红星
<el-table-column
prop="type"
label="type"
:render-header="addRedStar"
width="100px"
align="center"
>
<template slot-scope="scope">
<el-form-item
//保证唯一
:prop="'tableData.' + scope.$index + '.field'"
:rules="rules.field"
>
<el-select
v-model="scope.row.field"
placeholder="请选择"
>
<el-option
v-for="(item, index) in scope.row.field"
label="item.name"
value="item"></el-option>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="scenicArea" label="Value" align="center">
<template slot-scope="scope">
<!-- 选中的数据源筛选条件为日期 -->
<el-form-item
:prop="'tableData.' + scope.$index + '.ValueDatetime'"
v-if="scope.row.field.type == 'datetime'"
:rules="rules.ValueDatetime"
>
<el-date-picker
v-model="scope.row.ValueDatetime"
placeholder="选择日期"
value-format="yyyy-MM-dd HH:mm:ss"
type="datetime"
style="width: 80%"
>
</el-date-picker>
</el-form-item>
<!-- 选中的数据源筛选条件为string -->
<el-form-item
:prop="'tableData.' + scope.$index + '.ValueString'"
v-if="scope.row.field.type == 'string'"
:rules="rules.ValueString"
>
<el-select
v-model="scope.row.ValueString"
placeholder="请选择"
v-if="scope.row.field.options.length > 0"
>
<el-option
v-for="item in scope.row.field.options"
:key="item"
:label="item"
:value="item"
>
<span style="float: left">{{ item }}</span>
</el-option>
</el-select>
<el-input
v-model="scope.row.ValueString"
placeholder="请输入"
v-else
></el-input>
</el-form-item>
<!-- 选中的数据源筛选条件为Number -->
<el-form-item
:prop="'tableData.' + scope.$index + '.ValueNumeric'"
v-if="scope.row.field.type == 'numeric'"
:rules="rules.ValueNumeric"
>
<el-select
v-model="scope.row.ValueNumeric"
placeholder="请选择"
v-if="scope.row.field.options.length > 0"
>
<el-option
v-for="item in scope.row.field.options"
:key="item"
:label="item"
:value="item"
>
<span style="float: left">{{ item }}</span>
</el-option>
</el-select>
<el-input
type="number"
v-model="scope.row.ValueNumeric"
placeholder="请输入"
v-else
></el-input>
</el-form-item>
</template>
</el-table-column>
methods(){
// 表头生成必填校验红星样式
addRedStar(h, { column }) {
return [
h("span", { style: "color: red" }, "*"),
h("span", " " + column.label),
];
},
}
5.提交。你会发现我的Value那一列有三个字段:ValueString,ValueNumeric,ValueDatetime。是因为切换type的时候上一个选中的value我没做清空处理。就会导致页面没有但是数据中的value已存在。所以我就定了三个不同的字段。(另一种解决就是切换type的时候来调用select的click方法,传id然后更新tableData匹配后当前的value为“”)我懒没这样写
6.这个时候就不能用组件自带的方法来判断必填项是否填入了。用到了this.$refs.ruleForm.validate
7.避免多次点击保存调用接口。可以在加一个loading状态
<el-button
type="primary"
@click="submit"
>保存</el-button
>
submit() {
this.$refs.ruleForm.validate((valid, value) => {
if (valid) {
console.log(this.tableData)
}else{
this.$message.error("请填写必填项");
}
})
}
总结注意事项:1.table的唯一id,2.每一编辑行的唯一性el-form-item的**:prop=“‘filter.’ + scope.$index + ‘.field’”**,el-select的 v-model=“scope.row.field”。3.保存判断必填项