表格行内可编辑文本组件

表格行内编辑字段是一个非常常见的做法,实现也很简单,但是不同的人往往有不同的交互方式,比如我会加个编辑按钮表示可以编辑,还有的同学会使用双击触发编辑,也有单击的,有的同学会加一个✅图标保存,有的同学会使用enter来出发报错,有的。。。 总之是能想到的就能做到。

当然也有一些现成的表格组件封装好了各种行内编辑的方法,比如 vxe-table,一个功能很丰富的表格组件。但是我只想稍微给 el-table的表格加点花样,所以自己封装一个简单的组件更加轻便。

交互操作步骤

  1. 点击带【编辑】图标的字段,切换到编辑状态,并自动focus
  2. 失焦后保存数据,如果数据无变化无需走接口

考虑到编辑数字和普通文本,区别使用了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>

至此,实现了一个简单的行内编辑组件,如果有时间可以扩展得更加丰富一些,比如加上数据校验。

相关推荐
冬男zdn1 小时前
优雅处理数组的几个实用方法
前端·javascript
Kaze_story2 小时前
Vue第四节:组件化、组件生命周期
前端·javascript·vue.js
yuzhiboyouye2 小时前
web前端开发自测清单
前端
妮妮分享2 小时前
H5获取定位的方式是什么?
java·前端·javascript
weixin_439930642 小时前
前端js日期计算跨月导致的错误
开发语言·前端·javascript
niujiangyao2 小时前
vue v-for列表渲染, 无key、key为index 、 有唯一key三种情况下的对比。 列表有删除操作时的表现
vue.js
零一科技2 小时前
瑞吉外卖项目,前端源码(用户端)解析
前端
用户93051065822242 小时前
module federation,monorepo分不清楚?
前端·架构
柳安2 小时前
手写new操作符执行过程
前端·javascript
狗哥哥2 小时前
Vue 3 统一面包屑导航系统:从配置地狱到单一数据源
前端·vue.js·架构