可编辑的交互方式为,双击就将单元格中的内容转化为input输入框,失去焦点便保存。
项目使用的是element-ui的el-table,这里放一个el-table-column的列组件。
思路是,data里面定义一个对象来记录当前焦点所在的单元格的行信息和列信息,在每个单元格判断,当前焦点所在的单元格便渲染成 el-input 输入框。
<el-table-column
prop="bt"
label="电纳标幺"
width="110px"
align="center"
>
<template slot-scope="scope">
<el-input v-model="scope.row.bt"
type="number"
v-elInputFocus size="mini"
v-if="(scope.row.id === editCell.row.id
&& scope.column.id === editCell.col.id)"
@change="cellChange"
@blur="cellBlur"
></el-input>
<span v-else :class="isCellChanged('bt', scope) ? 'cell_changed' : ''">
{{ formatPoint(scope.row.bt, 6) }}
</span>
</template>
</el-table-column>
cellDblClick(row, column, cell, event){
// element-ui的单元格双击事件给了四个参数,分别是行、列信息,单元格dom对象,双击事件对象
// 我们这里记录行信息与列信息,用来定位焦点单元格。
this.editCell.row = row,
this.editCell.col = column;
},
cellChange(value){
/**
这里做的事情是发送修改数据的请求。
let form = {
field: this.editCell.col.property,
id: this.editCell.row.id,
modelTypeEnums: "LINE",
newValue: value
}
editModel(form)
.then( res => {
this.$message.success(`修改成功`);
this.getData();
})
*/
},
cellBlur(){
// 此函数在input失去焦点时触发,将记录定位单元格信息的对象置空。
this.$nextTick(() => {
// 这里要使用nextTick函数,否则cellChange函数内读取editCell对象值的时候就已经是空了。
this.editCell = {
row: {},
col: {}
}
})
},
在双击使需要编辑的单元格获得焦点时,这里在交互上有个小优化,单元格双击获得焦点后,其中的内容渲染成el-input输入框,这个时候的输入框是不会自动获取焦点的,也就意味着用户需要再次点击才能进行编辑。我们配合Vue的自定义指令来优化这一项。
与直接使用input元素不同的是,element-ui的el-input组件是一个div包裹了input组件,所以回调函数中的el参数获得的是input的父元素div,获得焦点的也是此div元素。所以我们在回调函数内需要获取el的子元素input,再调用focus()方法。
// 注册一个全局自定义指令 `v-elInputFocus`
Vue.directive('elInputFocus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
const elInput = el.querySelector("input");
elInput.focus()
}
})