表格行内可编辑文本组件

表格行内编辑字段是一个非常常见的做法,实现也很简单,但是不同的人往往有不同的交互方式,比如我会加个编辑按钮表示可以编辑,还有的同学会使用双击触发编辑,也有单击的,有的同学会加一个✅图标保存,有的同学会使用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>

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

相关推荐
小徐_23332 小时前
wot-ui-cli 1.1.0 发布:支持 OpenCode、Antigravity,wot-ui 图标迁移不再靠猜
前端
__zRainy__2 小时前
Node.js Web 框架选型指南:从 Express 到 Hono 的全景对比
前端·node.js·express·koa·nestjs·egg·fastify
西瓜有点饿2 小时前
PostCSS 和 UnoCSS 的作用和区别
前端·postcss
伟大的兔神3 小时前
我做了一个本地优先的 AI 图片工作台:Loomora v1.0.0 正式发布
前端·javascript·vue.js
90后的晨仔4 小时前
uni-app项目 Vue3 状态管理 Pinia 完全指南:从概念到实战的深度解析
前端
90后的晨仔4 小时前
uni-app 在 iOS 平台跳转页面时移除底部安全区域的完整技术指南
前端
用户938515635074 小时前
React + JWT 登录鉴权底层原理与工程化实践
前端·react.js
zww89491114 小时前
家政派单系统开发实战:架构设计与派单算法指南
前端·系统架构
fangzhanpeng1685 小时前
(前端)2.js变量作用域样例
开发语言·前端·javascript
赵广陆5 小时前
企业实战:web服务集成
前端·pycharm·fastapi