表格行内编辑字段是一个非常常见的做法,实现也很简单,但是不同的人往往有不同的交互方式,比如我会加个编辑按钮表示可以编辑,还有的同学会使用双击触发编辑,也有单击的,有的同学会加一个✅图标保存,有的同学会使用enter来出发报错,有的。。。 总之是能想到的就能做到。
当然也有一些现成的表格组件封装好了各种行内编辑的方法,比如 vxe-table,一个功能很丰富的表格组件。但是我只想稍微给 el-table的表格加点花样,所以自己封装一个简单的组件更加轻便。
交互操作步骤
- 点击带【编辑】图标的字段,切换到编辑状态,并自动focus
- 失焦后保存数据,如果数据无变化无需走接口
考虑到编辑数字和普通文本,区别使用了el-input和 el-input-number。
需要注意的一点就是,需要编辑后先自动聚焦,才能在失焦时触发保存,所以在此加入了指令v-focus,超级简单。
focus 指令
js
export default {
mounted(el: HTMLElement) {
el.querySelector('input')?.focus()
}
}
保存的时候,需要判断数据有没有发生变化,如果有变化才调用接口保存,否则直接变成非编辑状态即可。
接口 API 方法通过 props 传入,当然也可以写在调用该组件的父组件中,怎么灵活怎么来。
组件代码
js
<template>
<div>
<span class="inline-flex items-center cursor-pointer" @click="triggerEdit" v-if="!isActive"
>{{ value }} <el-icon color="#5F45FF" class="ml-2"><EditPen /></el-icon
></span>
<el-input-number
:min="0"
:max="9999"
:controls="false"
v-model="value"
class="w-30!"
v-focus
@blur="handleSortChange"
v-else-if="type === 'number'"
/>
<el-input
v-model="value"
class="w-30!"
v-focus
@blur="handleSortChange"
v-else-if="type === 'string'"
/>
</div>
</template>
<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { EditPen } from '@element-plus/icons-vue'
import { ref, computed, nextTick } from 'vue'
const props = defineProps({
type: { type: String, default: 'string' },
modelValue: { type: [String, Number], default: '' },
updateApi: { type: Function, default: () => {} },
rowData: { type: Object, default: () => {} },
paramName: { type: String, default: '' }
})
const emits = defineEmits(['success', 'update:rowData', 'update:modelValue'])
const value = computed({
get: () => {
return props.modelValue
},
set: (val) => {
emits('update:modelValue', val)
}
})
const isActive = ref(false)
const oldValue = ref()
const triggerEdit = () => {
oldValue.value = props.modelValue
isActive.value = true
}
const handleSortChange = () => {
if (oldValue.value === value.value) {
isActive.value = false
return
}
const postData = { ...props.rowData, [props.paramName]: value.value }
console.log(postData)
props
.updateApi(postData)
.then((res: any) => {
console.log(res)
if (res) {
ElMessage.success('排序成功')
isActive.value = false
}
})
.catch(() => {
value.value = oldValue.value
})
}
</script>
至此,实现了一个简单的行内编辑组件,如果有时间可以扩展得更加丰富一些,比如加上数据校验。