vue,form+table组合新增编辑弹框,table单元格可编辑,table单元格校验

本文详细描述了如何在Vue应用中使用el-table展示子表数据,每个单元格支持编辑,包括弹框添加新数据、表头筛选、数量校验等功能,以及添加和删除按钮的控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需求

1、新增数据时跳出弹框,弹框主子表显示
2、主表用form表单显示
3、子表用el-table显示,并且每个单元格都可编辑
4、子表applyQty有校验,applyQty>planQty触发验证消息,在修改每一行的数量的时候给出提示

最终实现样子

在这里插入图片描述

拆解需求 + 具体实现

1、form表单部分

这部分比较好实现,不过多赘述

<el-form :inline="true" class="demo-form-inline" label-position="right" label-width="130px" label-suffix=":" :rules="rules" ref="editForm" :model="editlist">
  <el-row>
    <el-col :span="12">
      <el-form-item label="项目名称" prop="bidName">
        <el-input v-model="editlist.bidName" placeholder="项目名称" clearable style="width: 200px"> </el-input>
      </el-form-item>
    </el-col>
    <el-col :span="12">
      <el-form-item label="类型" prop="outTypeReal">
     <-- DictSelect是自己封装的下拉框的组件,不重要 -->
        <DictSelect :dictType="'type_choose'" :value="editlist.outTypeReal" :isMultiple="false" placeholder="类型" style="width: 200px" @change="typeChange" :isClearable="true"> </DictSelect>
      </el-form-item>
    </el-col>
  </el-row>
</el-form>

2、el-table表格部分

2.1表头渲染

<template v-for="item in tableHeadConfig.headers">
	<template v-if="item.hvisible">
	</template>
</template>

这里循环渲染表头,并且可以在接口返回的数据里配置列是否显示

2.2 表头筛选插槽

<template #header v-if="showFilterRow">
  <headerParam :header="item" :ref="item.colid + '_param'" @children-change="paramChange" @children-enter="paramEnter" :showEmptyItem="showEmptyItem"> </headerParam>
</template>

2.3 单元格不同input输入插槽

<template #default="scope">
	<div class="input-box">
		<el-input size="small" v-model="scope.row[item.colid]"></el-input>
	</div>
</template>

2.4 单元格特殊输入

<-- 用v-if控制哪一列需要单独处理 -->
<-- 下面例:选择时间 -->
<el-date-picker v-model="scope.row[item.colid]" type="date" size="mini" v-if="item.colid === 'reqTime'" style="width: 120px"> </el-date-picker>

2.5 el-table部分完整代码

<el-table
  ref="dataTable"
  :data="tableData"
  border
  style="width: 100%; height: 450px"
  size="mini"
  highlight-current-row
  @header-dragend="widthChanged"
  element-loading-background="rgba(0, 0, 0, 0.5)"
  element-loading-text="正在加载中"
  @current-change="rowSelect"
  @sort-change="sortChange"
  :row-class-name="rowClass"
  :key="randomKey"
  @select="rowsCheck"
>
  <!-- 多选框 -->
  <el-table-column type="selection" width="40" :align="align"></el-table-column>
  <!-- 序列 -->
  <el-table-column label="序列" width="40px" align="center" fixed="left">
    <template #default="scope">
      <span>{{ scope.$index + 1 }}</span>
    </template>
  </el-table-column>
  <!-- 表头数据渲染 -->
  <template v-for="item in tableHeadConfig.headers">
    <!-- 如果列显示 -->
    <template v-if="item.hvisible">
      <el-table-column :prop="item.colid" :label="item.hlabel" :key="item.hlabel" :sortable="item.hsort" :width="item.hwidth" :align="item.align" :fixed="item.fixed" :show-overflow-tooltip="item.tip" header-align="center">
        <template #header v-if="showFilterRow">
          <headerParam :header="item" :ref="item.colid + '_param'" @children-change="paramChange" @children-enter="paramEnter" :showEmptyItem="showEmptyItem"> </headerParam>
        </template>
        <template #default="scope">
          <div class="input-box">
            <el-date-picker v-model="scope.row[item.colid]" type="date" size="mini" v-if="item.colid === 'reqTime'" style="width: 120px"> </el-date-picker>
            <div v-else-if="item.colid === 'applyQty'">
              <div v-if="editlist.busiType === '0' && scope.row.applyQty > scope.row.planQty">
                <el-row type="flex" align="middle" gutter="10">
                  <el-col :span="14">
                    <el-input-number v-model="scope.row.applyQty" controls-position="right" :min="0" :step="1" style="width: 120px" @change="applyQtyBlur"> </el-input-number>
                  </el-col>
                </el-row>
                <el-row>
                  <el-col :span="10">
                    <span style="color: red; font-size: smaller">申请数量不能大于计划数量</span>
                  </el-col>
                </el-row>
              </div>
              <div v-else>
                <el-input-number v-model="scope.row.applyQty" controls-position="right" :min="0" :step="1" style="width: 120px" @change="applyQtyBlur"> </el-input-number>
              </div>
            </div>
            <el-input size="small" v-model="scope.row[item.colid]" v-else></el-input>
          </div>
        </template>
      </el-table-column>
    </template>
  </template>
</el-table>
<-- 页签显示 -->
<el-pagination class="mt_8" v-model:current-page="page.pageNum" v-model:page-size="page.pageSize" small :background="background" layout="total, sizes, prev, pager, next, jumper" :total="page.total" @size-change="sizeChange" @current-change="sizeChange" />

3、控制table表格的添加和删除按钮

#vue部分

<el-form> ... <el-form>
<el-button type="primary" @click="insert">添加</el-button>
<el-button type="danger" @click="delData" v-if="outPlanShow">删除</el-button>
<el-table> ... </el-table>

#js部分
const initTableData = {
	
}
export default {
	data() {
		return {
			tableData: [],
			selectRows: [],
		}
	},
	methods: {
		insert() {
		   const tableData = JSON.parse(JSON.stringify(initTableData))
		   this.tableData.push(tableData)
		 },
		 rowSelect(row) {
	        this.selectRows= row
	     },
	     delData() {
	      if (this.selectRows.length === 0) {
	        this.$message.error('请选择数据')
	      } else {
	        const checkedData = this.selectRows.map((item) => item.index)
	        const tableData = this.tableData
	        this.tableData = tableData.filter((item) => checkedData.indexOf(item.index) === -1)
	      }
	    },
	}
}

4、数量校验

el-input-number无法加插槽,所以需要用div控制

<div v-else-if="item.colid === 'applyQty'">
  <div v-if="scope.row.applyQty > scope.row.planQty">
    <el-row type="flex" align="middle" gutter="10">
      <el-col :span="14">
        <el-input-number v-model="scope.row.applyQty" controls-position="right" :min="0" :step="1" style="width: 120px" @change="applyQtyBlur"> </el-input-number>
      </el-col>
    </el-row>
    <el-row>
      <el-col :span="10">
        <span style="color: red; font-size: smaller">申请数量不能大于计划数量</span>
      </el-col>
    </el-row>
  </div>
  <div v-else>
    <el-input-number v-model="scope.row.applyQty" controls-position="right" :min="0" :step="1" style="width: 120px" @change="applyQtyBlur"> </el-input-number>
  </div>
</div>
<think>嗯,用户想用Element Plus的el-table实现单元格可编辑功能。首先,我需要回忆一下Element Plus的文档和相关组件。记得el-table本身不直接支持可编辑单元格,但可以通过自定义模板和组件组合来实现。 首先,用户可能需要点击单元格进入编辑状态。这时候应该用作用域插槽(scoped slot)来自定义单元格内容。当点击时,显示一个输入,否则显示普通文本。需要用到v-if或v-show来控制显示状态。 然后,数据绑定是关键。el-table的数据通常是数组对象,每个单元格对应一个属性。在编辑时,需要将输入的值绑定到对应的数据属性上。可能需要使用v-model来实现双向绑定,但要注意作用域的问题,可能需要通过事件来更新数据。 接下来要考虑的是触发编辑的方式,比如单击或双击。用户可能需要通过事件处理函数来切换编辑状态。这时候需要给单元格添加@click或者@dblclick事件,并在处理函数中改变编辑状态变量。 另外,编辑完成后,可能需要触发保存操作。比如在输入失去焦点时保存数据,或者按回车键保存。这需要监听输入的blur事件或keyup.enter事件,然后调用保存函数更新数据。 还有样式的问题,编辑状态下可能需要高亮显示,或者调整输入的大小以适应单元格。这时候需要添加一些CSS类,或者内联样式来改善用户体验。 可能还需要处理表单验证,比如输入的内容是否符合要求。可以在保存数据前进行检查,或者使用Element Plus的表单验证组件。 另外,用户可能希望批量编辑多个单元格,这时候需要管理多个编辑状态,可能需要一个对象来记录每个单元格是否处于编辑模式,比如使用行的id和字段名作为键来存储状态。 还要考虑性能问题,特别是在大数据量的情况下,频繁的重新渲染可能会影响性能。这时候需要确保数据更新是响应式的,并且合理使用key属性来优化渲染。 最后,参考Element Plus的官方文档和示例代码,确保实现方式符合最佳实践,避免使用过时的API或方法。可能需要查看社区中的常见解决方案,比如使用el-input组件结合作用域插槽来实现可编辑单元格。 总结一下,步骤大致是:使用作用域插槽自定义单元格内容,通过事件切换编辑状态,绑定输入到数据,处理保存逻辑,以及样式和验证的优化。同时要注意状态管理和性能问题。</think>### Element Plus el-table实现单元格可编辑功能步骤 #### 一、基础实现方案 1. **使用作用域插槽** 通过`#default="scope"`自定义单元格内容,结合`v-if`切换输入和普通文本状态: ```vue <el-table :data="tableData"> <el-table-column prop="name"> <template #default="scope"> <el-input v-if="scope.row.editable" v-model="scope.row.name" @blur="saveEdit(scope.row)" /> <span v-else @click="toggleEdit(scope.row)">{{ scope.row.name }}</span> </template> </el-table-column> </el-table> ``` 2. **数据响应处理** 使用`reactive`创建响应式数据,通过`Object.assign`触发视图更新: ```javascript const tableData = reactive([/* 数据数组 */]); const toggleEdit = (row) => { row.editable = !row.editable; Object.assign(row, row); // 触发响应式更新 } ``` #### 二、进阶优化方案 1. **自动聚焦优化** 使用自定义指令实现输入自动聚焦: ```javascript app.directive('focus', { mounted(el) { el.querySelector('input').focus() } }) ``` 模板中增加指令: ```vue <el-input v-if="scope.row.editable" v-focus v-model="scope.row.name" /> ``` 2. **验证扩展** 结合Element Plus的`Form`组件进行数据校验: ```vue <el-form :model="scope.row" :rules="rules"> <el-form-item prop="name"> <el-input v-if="scope.row.editable" v-model="scope.row.name" @blur="validateField(scope.row)" /> </el-form-item> </el-form> ``` #### 三、完整实现示例 ```vue <template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="日期" width="180" /> <el-table-column prop="name" label="姓名"> <template #default="scope"> <div @click="handleClick(scope)"> <el-input v-if="scope.row.editable" v-focus v-model="scope.row.name" size="small" @blur="handleBlur(scope)" @keyup.enter="handleBlur(scope)" /> <span v-else>{{ scope.row.name }}</span> </div> </template> </el-table-column> </el-table> </template> <script setup> import { reactive } from 'vue'; const tableData = reactive([ { date: '2023-07-20', name: '张三', editable: false }, { date: '2023-07-21', name: '李四', editable: false } ]); const handleClick = (scope) => { if (!scope.row.editable) { scope.row.editable = true; Object.assign(scope.row, scope.row); } }; const handleBlur = (scope) => { scope.row.editable = false; Object.assign(scope.row, scope.row); console.log('保存数据:', scope.row); }; </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值