在项目中有一个需求是表格中有一列的数据可以点击修改,但是不能使用弹窗,需要在点击修改按钮时单元格内容变为输入框进行编辑,点击保存隐藏输入框,显示数据。
在一开始我的思路是在每行的对象中设置一个Boolean类型的标志位,在template标签中使用v-if来判断编辑状态,进而实现展示隐藏输入框,只有一行数据时测试没有问题,当数据量多了以后发现每次点击修改按钮,显示的输入框会串行显示,如下图:
这是原来错误的代码:
<el-table-column align="center" label="分数" width="100" :resizable="false" >
<template slot-scope="scope">
<div>
<el-form v-if="scope.row.editScoreFlag" :model="editScoreForm" ref="scoreForm" :rules="rules">
<el-form-item prop="score">
<el-input v-model="editScoreForm.score"></el-input>
</el-form-item>
</el-form>
<p v-else :class="scope.row.score<60 ? 'score-text':''" >{{ scope.row.score }}</p>
</div>
</template>
</el-table-column>
editScore(row, index) {
this.editScoreForm = {
courseId: this.$route.query.courseId,
id: row.id,
score: row.score
};
this.$set(this.studentScoreList[index], 'editScoreFlag', true);
},
问题出现在 v-if=“scope.row.editScoreFlag” 这一行上。因为 editScoreFlag 控制着是否显示 el-form 输入框,而这个值是保存在 scope.row 中的,而 scope.row 是由 v-for 渲染得来的,它们之间存在关联。由于editScoreFlag是行内没有的属性,我在点击修改时强行加进去的,在$data中没有定义,在 v-if 判断时,由于 v-for 会生成多个相同的 元素,当点击修改时,editScoreFlag 的值会改变,但由于该值并没有保存到对应的表格展示数据 studentScoreList 中,所以所有表格中的元素都发生了变化。
解决该问题有两种方法
- 需要把 editScoreFlag 作为studentScoreList 中的一个数据来保存,这样每个 元素中保存的都是当前列的状态,不会互相干扰。
- 将 v-if=“scope.row.editScoreFlag” 修改为 v-if=“scope.$index === rowEditIndex”, rowEditIndex 为当前列的索引,并将它保存在 $data 中。
下面的修改采用第二种方式:
<el-table-column align="center" label="分数" width="100" :resizable="false" >
<template slot-scope="scope">
<div>
<el-form v-if="scope.$index==editIndex" :model="editScoreForm" ref="scoreForm" :rules="rules">
<el-form-item prop="score">
<el-input v-model="editScoreForm.score"></el-input>
</el-form-item>
</el-form>
<p v-else :class="scope.row.score<60 ? 'score-text':''" >{{ scope.row.score }}</p>
</div>
</template>
</el-table-column>
export default {
data() {
return {
editIndex: -1,
}
},
methods: {
editScore(row, index) {
this.editScoreForm = {
courseId: this.$route.query.courseId,
id: row.id,
score: row.score
};
this.editIndex=index;
},
}
}
这样就可以解决上述问题了