最近在重构一个页面,需要把表格做成可编辑的。但是不巧的是Element框架里是没有可编辑表格的,所以只好自己来实现一个了。

实现起来不难,下面我给大家分享一下我是怎么做的。

表格怎么实现可编辑

其实思路很简单,主要利用普通显示和输入框之间的切换,来实现表格的编辑。

1
2
3
4
<template slot-scope="scope">
<span v-if="!scope.row.isEditing">{{ scope.row.name }}</span>
<span v-if="scope.row.isEditing"><el-input v-model="name" placeholder="请输入内容"></el-input></span>
</template>

比如像上面的代码这样,我们使用v-if(或v-show)指令来实现普通的显示和输入之间的切换。

这里使用到了slot-scope,这主要是用于把el-table-column的值传递到input里。

监听表格的点击

首先第一步肯定是去监听点击事件,看看点击了表格的哪里,我好切换输入框。

我本来是想在span上面绑定click的处理的,但是我发现el-table有一个cell-click的事件更加好用!

cell-click 当某个单元格被点击时会触发该事 row, column, cell, event

cell-click事件有row,column,cell这三个参数,我们可以凭这3个参数来判断现在被点击的是哪一行哪一列的表格。

1
2
3
<el-table :data="list" @cell-click="edit">
……
</el-table>

比如这样,当表格某个格子被点击的时候,我们就调用edit函数,可以在edit函数中进行处理,来切换输入框等。

怎么实现表格的文本与输入框的切换

现在我们知道,使用cell-click时间来监听表格的点击,在edit函数中实现文本与输入框的切换。

一开始的时候,我是想给表格的每一列都加一个对应的状态,比如isEditing1,isEditing2…用第一列v-if可以绑定row.isEditing1,我只要改变这个isEditing1的值为true或false,就可以控制切换了。像下面这样:

1
2
3
4
<template slot-scope="scope">
<span v-if="!scope.row.isEditing1">{{ scope.row.name }}</span>
<span v-if="scope.row.isEditing1"><el-input v-model="name" placeholder="请输入内容"></el-input></span>
</template>

但是这样的话还要加上那么多个状态,多少列数据就加多少个状态,太麻烦了,这个方案想了一下就被我放弃了。

后来我发现column里面有一个property属性,这个属性其实是数据的变量名。比如上面代码中,column.property = “name”。我只要加一个变量,存储被编辑的数据的变量名即可。当然column还有其他属性可以选择~

1
2
3
4
<template slot-scope="scope">
<span v-if="scope.row.editingColumn != 'name'">{{ scope.row.name }}</span>
<span v-if="scope.row.editingColumn == 'name'"><el-input v-model="name" placeholder="请输入内容"></el-input></span>
</template>

我给每一行数据加了一个属性editingColumn,顾名思义,是用来指明现在被编辑的是哪一列的数据。我只要在cell-click绑定的edit函数里,修改这个row.editingColumn即可:

1
2
3
edit: function(row, column, cell, event){
row['editingColumn'] = column.property;
}

而且不用担心这一整列数据都会变成输入框,因为我们是根据row参数来修改的,只是改了被点击的这一行的数据。所以只有这一行这一列的格子会变成输入框~

修改之后提交到后台保存

这是需求方提的需求,每修改一个数据就要刷新一次整个表格的数据。

我采用了2种方法:

  1. @blur失去焦点事件。当输入完成后,用户点击一下其他地方,输入框失去焦点后,就把输入框切换成文本,然后把数据提交到后台。
  2. 监听回车键@keyup.enter,如果输入完后用户点击了回车键,就把输入框切换成文本,然后把数据提交到后台。

输入框切换成文本跟文本切换成输入框一样,修改editingColumn的值即可。

后来我优化了一下,当数据被修改后再提交到后台,免得没修改也提交,浪费资源,影响体验。

获取焦点的问题

其实还有一个挺影响用户体验的问题,就是你把文本切换成输入框之后,这时候的输入框还是blur的,你还需要再点击一下,才能开始输入。

所以我们的目标也很明确了,就是要切换到输入框之后,马上给输入框获得焦点。

我们可以用vue的自定义指令来实现,大家可以看一下自定义指令的demo——
v-focus,刚好自定义指令的demo就是做了聚焦的例子。

1
2
3
4
5
6
7
8
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}

你在input标签加上v-focus属性,即可在被插入到DOM的时候获取到聚焦了。

研究了一个下午的,做出来我感觉体验还挺好的哈哈哈~