有一个简单的表格,产品要求实现双击可编辑
看了一下网上的帖子,大多数都是搞两部分dom,一块是输入框,用于编辑状态填写;另一块是普通标签,用于在不编辑显示状态下呈现单元格文字内容。再加上一个flag标识搭配v-if和v-else去控制编辑状态、还是显示状态。大致代码如下:
<el-table-column
align="center"
label="姓名"
>
<template slot-scope="scope">
<!--isClick就是标识状态,状态处于编辑时候,显示输入框,状态属于呈现状态就显示文本内容-->
<el-input v-if="scope.row.isClick" v-model="scope.row.name" @blur="blurFn(scope.row)"></el-input>
<span @click="clickCell(scope.row)" v-else>{{scope.row.name}}</span>
</template>
</el-table-column>
这种方式有其适用场景,但是得每个el-table-column列中都加上el-input和span以及v-if和v-else。我们尝试一下动态添加el-input,就是点击那个单元格,给那个单元格添加el-input让其处于可编辑状态,然后适时移除即可。这样的话,很多列的时候,就不用加很多个v-if和v-else啦。我们先看一下效果图

代码思路
- 第1步:给el-table绑定双击事件
@cell-dblclick='dblclick',再双击事件的回调函数中,可以得知点击的是哪一行、那一列、那个单元格dom,以及点击事件。dblclick(row, column, cell, event) {...},这个是饿了么官方提供的,没啥好说的 - 第2步:重点来喽
- 第2.1步:单元格双击事件以后,我们首先创建一个el-input标签,然后把点击的这个单元格的值,作为参数props让这个el-input接收,这样的话el-input就会显示这个单元格的值了,就可以编辑了。问题一:如何创建一个el-input标签? ,客官稍等,下方会解答
- 第2.2步:把创建好的el-input标签替换掉原来的单元格span标签,这样的话,就可以看到单元格变成了可输入的输入框了。问题二:如何把新创建的el-input标签,替换原有的span标签 ,客官稍等,下方会解答
- 第2.3步,当用户编辑完了点击别处时候,即输入框失去焦点的时候,再把el-input输入框标签移除掉,恢复默认的span标签(当然失去焦点的时候,就要发请求修改数据了)问题三:如何移除el-input标签,并恢复原有的span标签,客官稍等,下方会解答
- 这样的话,每次双击搞一个input标签用于修改,每次改完了失去焦点,就恢复默认单元格展示状态了,功能就实现了
问题一:如何创建一个el-input标签?
我们知道,如果是创建原生的input标签并指定一个值,比较简单,直接:
| 1 2 3 |
|
不过el-input标签不能通过上述方式创建,因为document.createElement()方法虽然可以创建出来el-input标签,但是dom并不认识这个el-input标签,所以页面没有变化。毕竟饿了么的el-input也是把input标签做一个二次封装的
所以,这里我们可以使用Vue.extend()方法去继承一个组件并暴露出去,而继承的这个组件中又有一个input标签,所以那个需要使用,那里就可以引入并new出来一个el-input了。关于Vue.extend()的定义啥的,这里不赘述,详情看官方文档。笔者之前也写过一篇Vue.extend文章,传送门:vue使用Vue.extend方法仿写个loading加载中效果实例_vue.js_脚本之家
首先搞一个.vue文件,用于继承
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
然后定义一个data.js文件,继承input.vue文件,并暴露
| 1 2 3 4 5 6 7 8 9 |
|
页面中引入并使用
| 1 2 3 4 5 6 7 8 9 |
|
propsData对象用于给继承的组件传递参数,也可以传递一个函数,从而继承组件通过这个函数通知外部使用组件,详情见后续完整代码
问题二三:el-input标签和span标签的来回替换恢复
使用$mount方法去做来回替换,$mount可以把一个子dom元素追加到父dom元素内部,相当于appendChild
然后这里需要有一个替换的时机,就是实例化的组件中的el-input失去焦点的时候,去通知外部使用的组件,所以可以在外部使用是,在propsData中传递一个函数到继承的组件,如:
| 1 2 3 4 5 6 7 8 9 10 11 |
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
所以当内层失去焦点的时候,就可以通知外层去做一个替换了,就是把单元格dom重新做一个$mount挂载,就把el-input替换成了span了,为了进一步理解,这里的span我们也可以使用继承的方式,是new实例化使用,详情见下方完整代码
完整代码
目录结构
threeC
-- data.js
-- input.vue
-- span.vue
three.vue
用于继承的el-input组件
input.vue
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
|
用于继承的span组件
span.vue
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
统一继承并暴露data.js文件
| 1 2 3 4 5 6 7 8 9 10 11 |
|
使用继承的three.vue组件
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
|
总结
使用Vue.extend()方法,可以继承一些组件,甚至继承一些复杂的组件,在实际业务场景中会有巧妙的使用。具体业务场景具体分析。
此外,上述代码中是el-input的继承,其实,我们也可以做el-select的继承,思路和上方类似,这样就可以在表格中双击单元格,选择并更改对应的下拉框更改el-table的单元值了,比如如果有性别这一列,那是下拉框的形式的。
文章介绍了如何在Vue中使用el-table实现单元格双击编辑功能,通过Vue.extend()方法动态创建和移除el-input组件,避免在每个列中硬编码v-if和v-else。在双击事件中创建el-input替换原有span,失去焦点时移除el-input并恢复span,从而实现编辑和显示状态的切换。这种方法减少了模板代码,提高了灵活性。

被折叠的 条评论
为什么被折叠?



