最终实现:列表内容双击、行内编辑、控件失焦提交接口修改

一、简单实现: 有bug,双击后文本框获取不到焦点

- VUE相关代码:
html
<template>
<!-- 列表 -->
<ContentWrap>
<el-table :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column label="流程备注" align="center" width="200">
<template #default="scope">
<span v-if="!scope.row.isEditing" @dblclick="startEditing(scope)" > {{ scope.row.name }} </span>
<el-input v-else v-model="scope.row.name" @keyup.enter="stopEditing(scope)" @blur="stopEditing(scope)" />
</template>
</el-table-column>
</el-table>
</ContentWrap>
</template>

javascript
<script lang="ts" setup>
// 获取列表数据示例:
const list = ref([]) // 列表数据(接口获取)
/** 接口查询列表数据 */
const getList = async () => {
try {
//查询列表数据 示例
const data = await ContractApi.getContractPage(queryParams)
list.value = data.list
} finally {
}
}
// 以下是行内编辑相关
let lastEditValue = "" //双击行内编辑文本内容(记录并用于判断提交时是否执行接口提交)
/** 双击文本,进入编辑状态 **/
const startEditing = (scope) => {
lastEditValue = scope.row.name //双击行内编辑文本内容
scope.row.isEditing = true
}
/** 回车键 或 编辑框失去焦点(如:点击编辑框外任意点),提交修改内容到接口 **/
const stopEditing = (scope) => {
scope.row.isEditing = false
// 行内编辑前后内容不同,提交修改后数据
if(lastEditValue.trim() !== scope.row.name?.trim()){
alert(scope.row.name?.trim())
// 这里可以添加保存或其他逻辑
}
}
</script>

- 后端代码:分页查询的集合对象中,新增属性 isEditing 用于标记是否是双击编辑状态
java
/** 是否编辑状态(配合行内编辑使用):默认 否 **/
private boolean isEditing = false;

二、双击后自动设置焦点全版本:
- VUE相关代码:
html
<template>
<!-- 列表 -->
<ContentWrap>
<el-table :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column label="流程备注" align="center" width="200">
<template #default="{ row, $index }">
<span v-if="!row.isEditing" @dblclick="startEditing(row, $index)" > {{ row.name }} </span>
<el-input v-else :ref="(el) => setInputRef(el, $index)" v-model="row.name" @keyup.enter="stopEditing(row, $index)" @blur="stopEditing(row, $index)" />
</template>
</el-table-column>
</el-table>
</ContentWrap>
</template>
<script lang="ts" setup>
import { ref, nextTick } from 'vue' //双击行内编辑聚集相关
// 获取列表数据示例:
const list = ref([]) // 列表数据(接口获取)
/** 接口查询列表数据 */
const getList = async () => {
try {
//查询列表数据 示例
const data = await ContractApi.getContractPage(queryParams)
list.value = data.list
} finally {
}
}
// 以下是行内编辑相关
// 保存每个输入框的引用(按行索引)
const inputRefs = ref([])
const setInputRef = (el, index) => {
if (el) {
inputRefs.value[index] = el
}
}
/** 双击文本,进入编辑状态 **/
const startEditing = async (row, index) => {
row._oldName = row.name // 存储旧值到行对象:双击行内编辑文本内容(记录并用于判断提交时是否执行接口提交)
row.isEditing = true //编辑中
// 等待 DOM 更新后聚焦
await nextTick()
// 获取对应行的 el-input 组件实例
const inputInstance = inputRefs.value[index]
if (inputInstance) {
// 方法1:直接调用组件暴露的 focus
inputInstance.focus?.()
// 如果无效,降级到原生 input(但通常 focus 方法已足够)
// inputInstance.$el.querySelector('input')?.focus()
}
}
/** 回车键 或 编辑框失去焦点(如:点击编辑框外任意点),提交修改内容到接口 **/
const stopEditing = async (row, index) => {
row.isEditing = false
const oldName = row._oldName
// 行内编辑前后内容不同,提交修改后数据
if(oldName.trim() !== row.name?.trim()){
try {
await ContractApi.updateInvoice(row.id, row.name) // 发起修改
delete row._oldName // 清除临时数据
// await getList() // 刷新列表
} catch {
// await getList()
row.name = oldName// 恢复原值
}
}
}
</script>
- 后端代码:分页查询的集合对象中,新增属性 isEditing 用于标记是否是双击编辑状态
java
/** 是否编辑状态(配合行内编辑使用):默认 否 **/
private boolean isEditing = false;
