实现一个可编辑的表格,让用户可以修改表格中的数据,并且能够清楚地看到哪些单元格被修改过。这样的功能可以提高用户体验,也方便后端处理数据的变化。
本文将介绍如何使用Vue.js和Element UI的el-table组件来实现一个可编辑表格,并且修改的单元格会有不同的背景色。
代码实现
首先创建一个el-table组件,给它绑定一个data属性,用来存储表格的数据。给每个el-table-column设置一个prop属性,用来指定每一列对应的数据字段。使用v-for指令来动态生成表格的列,根据一个tableColumn数组,里面存储了每一列的信息,比如label,prop,fixed等。可以给el-table添加一些事件监听,比如cell-mouse-enter,cell-mouse-leave,cell-click等,用来实现鼠标移入移出和点击单元格的效果。代码如下:
<el-table ref="multipleTable" stripe :border=true :data="tableData"@cell-mouse-enter="handleCellEnter" @cell-mouse-leave="handleCellLeave" @cell-click="handleCellClick":cell-style="cellstyle"><el-table-column width=120 v-for="column in tableColumn" :key="column.aliasColName":prop="column.aliasColName" :label="column.text" :fixed="column.fixed"><div class="item" v-if="column.editStyle == 5"slot-scope="scope"><el-input class="item__input" v-model="scope.row[scope.column.property]" placeholder="请输入内容"><i slot="suffix" class="el-icon-edit" @click="showPwd(scope.row, scope.$index, scope.column)"></i></el-input><div class="item__txt">{{ scope.row[scope.column.property] }}</div></div><div class="item" v-else-if="column.editStyle == 22" slot-scope="scope"><el-select v-model="scope.row[scope.column.property]" placeholder="请选择"><el-option v-for="item in listArray" :key="item.value" :label="item.display" :value="item.value"></el-option></el-select></div></el-table-column><el-table-column fixed="right" label="操作" width="120" v-if="!visremove"><div class="item" slot-scope="scope"><el-popconfirm confirm-button-text='好的' cancel-button-text='取消' icon="el-icon-info" icon-color="red"title="确定删除吗?" @confirm="removerow(scope.row)"><el-button slot="reference" type="text" size="small">删除</el-button></el-popconfirm></div></el-table-column></el-table>
接下来需要在data中定义一些变量,用来存储表格的数据,列的信息,下拉框的选项,以及一些控制变量,比如clickSwitch,用来记录当前点击的单元格,clickCellMap,用来存储当前点击的单元格的DOM元素,tableDataCopy,用来存储表格数据的副本,用于和修改后的数据进行对比。代码如下:
data() {return {tableData: [], //表格数据tableColumn: [], //表格列信息listArray: [], //下拉框选项clickSwitch: { //当前点击的单元格row: "",col: ""},clickCellMap: [], //当前点击的单元格的DOM元素tableDataCopy: [], //表格数据的副本};},
然后,需要在mounted中调用一个loadtabledata方法,用来加载表格的数据和列的信息。这里使用了一个模拟的数据文件loadData.json,里面存储了表格的数据和列的信息。根据实际的需求,从后端获取数据或者自定义数据。还需要使用JSON.parse和JSON.stringify方法,来创建一个表格数据的副本,用于后续的对比。代码如下:
mounted() {this.loadtabledata();},methods: {//表格loadtabledata() {let resloadtabledata = require("@/artificialdata/loadData.json")this.tableData = resloadtabledata.data.datathis.tableDataCopy = JSON.parse(JSON.stringify(resloadtabledata.data.data))},}
接下来实现一些事件处理的方法,用来实现鼠标移入移出和点击单元格的效果。handleCellEnter方法用来处理鼠标移入单元格的事件。获取当前单元格的column和cell,然后判断是否有prop属性,如果有,说明是可编辑的单元格,就给它的item__txt类添加一个item__txt–hover类,用来显示一个编辑图标,提示用户可以点击编辑。代码如下:
/** 鼠标移入cell */handleCellEnter(row, column, cell, event) {const property = column.propertyif (property) {cell.querySelector('.item__txt').classList.add('item__txt--hover')}},
然后,需要实现一个handleCellLeave方法,用来处理鼠标移出单元格的事件。需要获取当前单元格的column和cell,然后判断是否有prop属性,如果有,说明是可编辑的单元格,就给它的item__txt类移除一个item__txt–hover类,用来隐藏编辑图标。代码如下:
/** 鼠标移出cell */handleCellLeave(row, column, cell, event) {const property = column.propertyif (property) {cell.querySelector('.item__txt').classList.remove('item__txt--hover')}},
接下来,实现一个handleCellClick方法,用来处理点击单元格的事件。获取当前单元格的row,column,cell,然后判断是否是同一个单元格,如果是,就不做任何操作,如果不是,就记录当前点击的单元格的信息,存储到clickSwitch变量中。然后,需要判断是否有之前点击的单元格,如果有,就触发它的失焦事件,让它保存数据,并且切换它的显示状态,让它显示文本,隐藏输入框。最后,切换当前点击的单元格的显示状态,让它显示输入框,隐藏文本,并且让输入框获取焦点。代码如下:
/** 点击cell */handleCellClick(row, column, cell, event) {if (this.clickSwitch.row == row.id && this.clickSwitch.col == column.property) {return}this.clickSwitch.row = row.idthis.clickSwitch.col = column.propertyconst property = column.property// 保存cellif (this.clickCellMap.length > 0 ) {this.clickCellMap[0].querySelector('input').blur()}if (this.clickCellMap.length > 0) {this.clickCellMap[0].querySelector('.item__txt').style.display = 'block'this.clickCellMap[0].querySelector('.item__input').style.display = 'none'}this.clickCellMap[0]=cellcell.querySelector('.item__txt').style.display = 'none'cell.querySelector('.item__input').style.display = 'block'cell.querySelector('input').focus()},
最后实现一个cellstyle方法,用来设置单元格的样式。需要获取当前单元格的row,column,rowIndex,columnIndex,然后判断当前单元格的值是否和表格数据副本中的值相同,如果不同,就说明该单元格被修改过,就给它返回一个背景色的样式,比如"background-color: rgb(144 199 255);",让它显示为蓝色。这样,用户就可以一眼看出哪些单元格被修改过,哪些没有。代码如下:
cellstyle({ row, column, rowIndex, columnIndex }) {if (this.tableDataCopy[rowIndex][column.property] != row[column.property]) {return "background-color: rgb(144 199 255);"}},
效果展示
表格中有两种类型的可编辑单元格,一种是输入框,一种是下拉框。当鼠标移入一个可编辑的单元格时,它会显示一个编辑图标,提示可以点击编辑。当点击一个可编辑的单元格时,它会显示一个输入框或者下拉框修改数据。当修改完数据后,按下回车键或者点击其他地方,它会保存数据,并且切换回文本显示。同时可以看到,修改过的单元格会有一个蓝色的背景色,清楚地看到数据的变化。还可以点击右侧的删除按钮,删除一行数据。代码如下:
cellstyle({ row, column, rowIndex, columnIndex }) {if (this.tableDataCopy[rowIndex][column.property] != row[column.property]) {return "background-color: rgb(144 199 255);"}},
.el-input__icon {line-height: 24px !important;
}.el-button--text {height: 24px;}.item {.el-input--suffix .el-input__inner {padding-right: 20px;padding-left: 10px;}.el-input__inner {height: 24px !important;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;}.item__input {display: none;}.item__txt {box-sizing: border-box;border: 1px solid transparent;width: 100px;line-height: 24px;padding: 0 8px;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;}.item__txt--hover {border: 1px solid #dddddd;border-radius: 4px;cursor: text;}
}
.el-table {.el-table__cell {padding: 6px 0 !important;}}