vue3 element el-table实现表格动态增加/删除/编辑表格行,带有校验规则

需求描述

在项目中遇到需要实现表格动态的新增、编辑、删除表格行的需求,同时带有校验规则

代码解决

  1. 点击新增的时候,给新增row默认属性,给相应的默认值,包括给一个isEditor: true,用来区分是否需要编辑。同时当有编辑行的时候,应当不能新增新的行或者编辑其他行,全局定义一个isHasEdit,用来分辨当下是否有正在编辑的行。
bash 复制代码
const isHasEdit = ref('1') // 1 默认没有正在编辑的, 0 有正在编辑的row,其他row不能编辑/新增
const addRow = (index: number) => {
    if(isHasEdit.value == '1') {
        tableData.value.splice(index + 1, 0, {
            key: "",
            value: "",
            isEditor: true
        })
        isHasEdit.value = '0'
    }
}
  1. 当isEditor为true的时候能编辑,表格当中要插入相应需求的el-form-item,通过isEditor判断是否显示
bash 复制代码
<el-form :model="tableData" ref="tableForm">
                        <div class="btn">
                            <el-button type='primary' link @click='addRow(tableData.length-1)'>新增行</el-button>
                        </div>
                        <el-table :data="tableData" stripe border header-cell-class-name='x-table-header' cell-class-name='x-table-cell'>
                            <el-table-column type="index" width="60" label="序号" align="center"></el-table-column>
                            <el-table-column prop="key" label="职级" align="center">
                                <template #default="{row, $index}">
                                    <el-form-item 
                                        v-if="row.isEditor"
                                        :prop="`${$index}.key`"
                                        :rules="rules.key"
                                    >
                                        <el-input v-model="row.key" />
                                    </el-form-item>
                                    <span v-else>{{ row.key }}</span>
                                </template>
                            </el-table-column>
                            <el-table-column prop="value" label="金额/天" align="center">
                                <template #default="{row, $index}">
                                    <el-form-item
                                        v-if="row.isEditor"
                                        :prop="`${$index}.value`"
                                        :rules="rules.value"
                                    >
                                        <el-input v-model="row.value"/>
                                    </el-form-item>
                                    <span v-else>{{ row.value }}</span>
                                </template>
                            </el-table-column>
                            <el-table-column label="操作" align="center">
                                <template #default="{row, $index}">
                                    <el-button type='primary' v-if="!row.isEditor" text @click="editRow(row, $index)">编辑</el-button>
                                    <el-button type="primary" v-else text @click="saveRow(row, $index)">保存</el-button>
                                    <el-button type="danger" text @click="delRow(row.id, $index)">删除</el-button>
                                </template>
                            </el-table-column>

                        </el-table>
                    </el-form>

:prop="${$index}.value" 动态的绑定,确保相应正确校验

3.完整代码

bash 复制代码
<script lang="tsx" setup>
const tableData = ref<any[]>([])
const isHasEdit = ref('1') // 1 默认没有正在编辑的, 0 有正在编辑的row,其他row不能编辑/新增
const addRow = (index: number) => {
    if(isHasEdit.value == '1') {
        tableData.value.splice(index + 1, 0, {
            key: "",
            value: "",
            isEditor: true
        })
        isHasEdit.value = '0'
    }
}

const editRow = (row:any, index: number) => {
    // row.isEditor = true;
    // tableData.value[index].isEditor = true
    if(isHasEdit.value == '1') {
        tableData.value[index].isEditor = true
        isHasEdit.value = '0'
    }
}
const tableForm = ref();
const rules = ({
    key: [{ required: true, message: '请输入', trigger: 'blur' }],
    value: [{ required: true, message: '请输入', trigger: 'blur' }],
})
const saveRow = (row:any, index:number) => {
    tableForm.value?.validate(async(valid:any) => {
        if(valid) {
            row.id ? await updateConfig({...row, type: 0}) : await addConfig({...row, type: 0})
            tableReset()
            isHasEdit.value = '1'
            row.isEditor = false;
        }
    })
    
}
const delRow = (id:any, index: number) => {
    ElMessageBox.confirm(
        '即将删除该职级,是否继续',
        '提示',
        {
            confirmButtonText: '确 定',
            cancelButtonText: '取 消',
            type: 'warning'
        }
    ).then(async () => {
        isHasEdit.value = '1'
        
        if(id) { // 已保存(存入数据库)数据的删除
            await delConfig(id)
            // tableData.value.splice(index, 1)
            tableReset()
        }else { // 新增数据,没有存入数据库的数据删除
            tableData.value.splice(index, 1)
        } 
    }).catch(()=>{
        isHasEdit.value = '0'
    })
}
</script>
<template>
<div class="tab">
        <el-form :model="tableData" ref="tableForm">
            <div class="btn">
                <el-button type='primary' link @click='addRow(tableData.length-1)'>新增行</el-button>
            </div>
            <el-table :data="tableData" stripe border header-cell-class-name='x-table-header' cell-class-name='x-table-cell'>
                <el-table-column type="index" width="60" label="序号" align="center"></el-table-column>
                <el-table-column prop="key" label="职级" align="center">
            
                    <template #default="{row, $index}">
                        <el-form-item 
                            v-if="row.isEditor"
                            :prop="`${$index}.key`"
                            :rules="rules.key"
                        >
                            <el-input v-model="row.key" />
                        </el-form-item>
                        <span v-else>{{ row.key }}</span>
                    </template>
                </el-table-column>
                <el-table-column prop="value" label="金额/天" align="center">
                    <template #default="{row, $index}">
                        <el-form-item
                            v-if="row.isEditor"
                            :prop="`${$index}.value`"
                            :rules="rules.value"
                        >
                            <el-input v-model="row.value"/>
                        </el-form-item>
                        <span v-else>{{ row.value }}</span>
                    </template>
                </el-table-column>
                <el-table-column label="操作" align="center">
                    <template #default="{row, $index}">
                        <el-button type='primary' v-if="!row.isEditor" text @click="editRow(row, $index)">编辑</el-button>
                        <el-button type="primary" v-else text @click="saveRow(row, $index)">保存</el-button>
                        <el-button type="danger" text @click="delRow(row.id, $index)">删除</el-button>
                    </template>
                </el-table-column>

            </el-table>
        </el-form>
        
    </div>
</template>
相关推荐
Eric.461 小时前
Wan‑Animate+MiniMax-H3 本地部署 AI 漫剧流水线:8G 显存动作迁移与动态分镜工程实战
前端·人工智能·comfyui·ai漫剧
liangshanbo12151 小时前
JavaScript 异步核心主线
javascript·事件循环·异步操作
传人once2 小时前
悬停旋转放大和位移效果如何写
javascript·css·动画
库拉镜像AI牛牛2 小时前
短剧内容自动化生产:知漫剧工作室落地教程
大数据·服务器·前端·人工智能·语音识别
律宏阔3 小时前
Flutter 列表图片内存优化:CachedNetworkImage 与 ClipRRect 的取舍
前端·flutter
行者全栈架构师3 小时前
【鸿蒙心迹】相册文搜图工程化落地:HarmonyOS 7.0 端侧 AI 检索全链路实战与 5 个踩坑解法
前端
律宏阔3 小时前
Dart 3 Record:解决 Future.wait 异构返回值的类型问题
前端·flutter
Seraphina363 小时前
DVWA(XSS Reflected/Stored High,CSRF Low)
前端·xss·csrf
默_笙4 小时前
🍔 中间件不只是打日志:四个钩子、一次短路,和自带的工具
前端·javascript
程序员老赵4 小时前
Docker 部署 Dolibarr:轻松搭建开源 ERP/CRM 平台
运维·前端·后端