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>
相关推荐
HelloReader3 分钟前
Flutter 自适应布局一套代码适配手机和平板(十二)
前端
牛奶6 分钟前
HTTP裸奔,HTTPS穿盔甲——它们有什么区别?
前端·http·https
梓言8 分钟前
tailwindcss构建执行npm exec tailwindcss init -p 报错
前端
哈罗哈皮9 分钟前
龙虾(openclaw)本地快速安装及使用教程
前端·aigc·ai编程
用户231154445305810 分钟前
React中实现“双向绑定”效果的几种方式
前端
HelloReader11 分钟前
Flutter Sliver 高级滚动打造 iOS 通讯录体验(十三)
前端
a11177643 分钟前
程序化几何背景生成器(html 开源)
前端·开源·html
浮笙若有梦1 小时前
我开源了一个比 Ant Design Table 更好用的高性能虚拟表格
前端·vue.js
一只程序熊1 小时前
vite-cool-unix-ctx] Unexpected token l in JSON at position 0
java·服务器·前端
张元清1 小时前
React Hooks vs Vue Composables:2026 年全面对比
前端·javascript·面试