Element-UI组件中Form表单resetFields()重置方法踩过的坑以及Vue中Axios同步异步请求踩过的坑,分享给大家!

博客讲述了在Vue项目中使用Element-UI的Form表单时遇到的resetFields()重置方法问题,以及在处理数据初始化时由于Axios的异步特性导致的困扰。作者通过尝试同步请求解决这个问题,最终使用jQuery的Ajax实现同步,成功解决问题。

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

关于Form表单中restFields()方法的官方解释

restFields()方法说明:对整个表单进行重置,将所有字段值重置为初始值并移除校验结果。

根据字面意思理解,调用这个方法会将表单所填写的数据重置为初始值并且移除表单校验的结果。

我最开始所理解的“初始化数据”是指的实例化Vue时在data中所声明的数据。如下图所示:
data中所声明的数据
也就是说,调用restFields()会将数据充值为这里所声明的初始化数据。

在Vue中对表单初始化数据赋值,调用created函数

代码如下:

created: function() {
	axios.get("/index/oauth/getUserInfo", {
		params: {
			openId: this.openId
		}
	}).then((response) => {
		if (response.data.httpCode == 200) {
			let info = response.data.data;
			if (info.sex == 1) {
				info.sex = '男';
			} else if (info.sex == 0) {
				info.sex = '女';
			} else {
				info.sex = '未知';
			}
			// 将服务器返回的数据赋值给表单model
			this.ruleForm = info;
			if (info.userType == 2) {
				this.accountText = '学号';
				this.instituteText = '学院';
			} else {
				this.accountText = '工号';
				this.instituteText = '部门';
			}
		} else {
			this.$message.error(response.data.msg);
		}
	}).catch((error) => {
		console.error(error);
	});
}

前端页面截图如下:(因业务需求,工号,姓名以及部门不能修改)
前端页面截图
一切正常,没有任何问题,关键点来了。

调用resetFields()方法重置表单

重置按钮的单击事件

<el-button @click="resetForm('ruleForm')">重置</el-button>

相对应调用的事件

resetForm(formName) {
	this.$refs[formName].resetFields();
}

问题就出现在这里,将我表单里面所有的数据都重置为data里面声明的初始值了,如下图所示:
重置表单数据的截图
工号,姓名以及部门都是禁用了的,数据重置过后用户也无法填写,这肯定不行啊,如何能重置为created函数里所初始化的数据呢?

经过网上资料查询,resetFields()方法会将表单数据重置为created函数里所初始化的数据,我就是在created函数中初始化的数据啊,为什么全部给我重置成data中的数据了?有毒?

后来我做了各种测试,各种查资料,各种写法测试,都还是不行。

例如:我将data中的数据赋值为null,我不声明初始值
data中初始值为null
这样做没问题!调用resetFields()重置表单过后,表单数据还在,而且是created函数中所初始化的数据,但是页面刷新的时候控制台会抛出一个新的错误,如下图所示:
控制台打印错误
实例化Vue的时候显示account属性为null,对于强迫症的我来说,肯定不允许这样的错误存在!所以我将data中的属性还是重新声明了并赋了初始值,那么问题回来了,重置表单的时候如何将数据保留在表单中呢?

为了验证“resetFields()方法会将表单数据重置为created函数里所初始化的数据”这句话,我在created函数中写死了数据,如下所示:

created: function() {
	this.ruleForm = {
		account: '123456',
		name: '张三',
		nickname: '梦想'
	}
}

当页面重置表单的时候,数据保留了下来,那就证明这句话是没问题的!那么我这里问题出在哪里呢?我明明也是在created函数中初始化的数据啊!

我仔细想了想,为什么写死数据没问题,一用Axios请求数据就出问题了呢?难道问题出在Axios上?我将Axios请求的数据用一个变量接收,并且在控制台打印出来,果然发现了不以样的地方!

created: function() {
	let data = axios.get("/index/consult/getAll", {
		params: {
			openId: this.openId
		}
	});
	console.log(data);
}

控制台打印的结果如下图所示:
控制台输出结果
诶嘿,Promise是什么鬼?似曾相识的感觉,赶紧问问度娘。
网上资料解释:Promise是异步编程的一种解决方法。(关于Promise的详细资料请自行上网查找)

异步!异步!异步!肯定就是这问题了!

遂百度Axios如何进行同步请求,因为第一次写Vue的项目,第一次使用Axios,所以我觉得应该就像Ajax那样设置async: false就可以同步请求了吧。

网上查找了一圈,基本上都说的是使用async+await来现实同步请求,在methods中声明函数调用,语法如下:

methods: {
    async funA(){
        var res =  await axios.post(''); //这里的res就是axios请求回来的结果
    }
}

我试着写了一下,在methods中声明一个函数,并且在created中调用。

created: function() {
	this.getUserInfo();
},
methods: {
	async getUserInfo() {
		let response = await axios.get("/index/oauth/getUserInfo", {
			params: {
				openId: this.openId
			}
		});
		if (response.data.httpCode == 200) {
			let info = response.data.data;
			if (info.sex == 1) {
				info.sex = '男';
			} else if (info.sex == 0) {
				info.sex = '女';
			} else {
				info.sex = '未知';
			}
			// 将服务器返回的数据赋值给表单model
			this.ruleForm = info;
			if (info.userType == 2) {
				this.accountText = '学号';
				this.instituteText = '学院';
			} else {
				this.accountText = '工号';
				this.instituteText = '部门';
			}
		} else {
			this.$message.error(response.data.msg);
		}
	}
}

页面刷新,表单数据初始化成功,但是当我点击重置的时候,数据还是没了…

难道是我同步请求写的不对吗?继续查询网上资料,写法基本上都大同小异,各种写法我都测试过,最终都以失败告终。

后看到有一片博客说Axios不支持同步请求,都是用的Ajax实现的同步请求。于是我放弃了,妥协了,在页面用引入了jQuery,使用Ajax同步请求,问题成功解决!也证明了确实就是异步请求所造成的的问题!代码如下:

created: function() {
	this.getUserInfo();
},
methods: {
	getUserInfo() {
		let vm = this;
		$.ajax({
			type: "get",
			url: "/index/oauth/getUserInfo",
			dataType: "json",
			async: false, // 同步请求
			data: {
				openId: this.openId
			},
			success: function(result) {
				if (result.httpCode == 200) {
					let info = result.data;
					if (info.sex == 1) {
						info.sex = '男';
					} else if (info.sex == 0) {
						info.sex = '女';
					} else {
						info.sex = '未知';
					}
					vm.ruleForm = info;
					if (info.userType == 2) {
						vm.accountText = '学号';
						vm.instituteText = '学院';
					} else {
						vm.accountText = '工号';
						vm.instituteText = '部门';
					}
				} else {
					vm.$message.error(result.msg);
				}
			}
		});
	},
}

总结:第一次做Vue的项目,Element-UI很好用,准备以后长期使用。不过有一个疑问,Vue官方推荐使用的Axios不支持同步请求吗?不应该啊!也许是我不知道,还望知道的前辈能指导一下。这也是我第一次写博客,写的不好的地方还请见谅,谢谢。

<think>我们使用Element UI的el-table和el-form组件来构建一个支持增删改查(CRUD)的前端界面。以下步骤将包括: 1. 搭建基本表格(el-table)显示数据 2. 使用表单(el-form)进行增加和修改操作 3. 为每个操作(增删改查)预留API请求函数 注意:这里我们主要关注前端界面的搭建和函数预留,实际的API请求函数需要根据后端接口实现。 步骤: 一、基本表格展示 使用el-table展示数据,并添加操作列(编辑和删除按钮)。 二、表单对话框 使用el-dialog包裹el-form,用于添加和编辑数据。通过一个变量控制对话框的显示与隐藏。 三、操作按钮 添加“新增”按钮,点击弹出表单对话框;在表格每一行的操作列添加“编辑”和“删除”按钮。 四、数据与方法 定义数据对象,包括表格数据、表单数据、对话框是否可见等状态。 五、预留API请求函数 定义四个函数分别对应增删改查操作,这些函数内部将发送HTTP请求(使用axios等),这里我们先留空,仅打印日志。 代码结构如下: 1. 模板部分(Template) 2. 脚本部分(Script) 我们将使用Vue单文件组件(SFC)格式编写。 注意:确保已经安装并引入了Element UI。 下面是一个完整的示例代码:</think>下面我将详细介绍如何使用 Element UI 的 `el-table` 和 `el-form` 组件实现一个支持增删改查(CRUD)功能的前端界面,并预留 API 请求函数。 ### 完整实现方案 ```vue <template> <div class="crud-container"> <!-- 搜索区域 --> <el-form :inline="true" class="search-form"> <el-form-item label="名称"> <el-input v-model="searchQuery.name" placeholder="输入名称"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="handleSearch">查询</el-button> <el-button @click="resetSearch">重置</el-button> </el-form-item> </el-form> <!-- 操作按钮 --> <div class="action-buttons"> <el-button type="primary" icon="el-icon-plus" @click="openCreateDialog"> 新增 </el-button> </div> <!-- 数据表格 --> <el-table :data="tableData" border style="width: 100%" v-loading="loading" > <el-table-column prop="id" label="ID" width="100"></el-table-column> <el-table-column prop="name" label="名称"></el-table-column> <el-table-column prop="status" label="状态"> <template slot-scope="scope"> <el-tag :type="scope.row.status ? 'success' : 'danger'"> {{ scope.row.status ? '启用' : '禁用' }} </el-tag> </template> </el-table-column> <el-table-column prop="createTime" label="创建时间"></el-table-column> <!-- 操作列 --> <el-table-column label="操作" width="200"> <template slot-scope="scope"> <el-button size="mini" @click="openEditDialog(scope.row)" >编辑</el-button> <el-button size="mini" type="danger" @click="handleDelete(scope.row)" >删除</el-button> </template> </el-table-column> </el-table> <!-- 分页组件 --> <el-pagination @size-change="handleSizeChange" @current-change="handlePageChange" :current-page="pagination.currentPage" :page-sizes="[10, 20, 50]" :page-size="pagination.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" ></el-pagination> <!-- 新增/编辑对话框 --> <el-dialog :title="dialogType === 'create' ? '新增数据' : '编辑数据'" :visible.sync="dialogVisible" width="600px" > <el-form :model="formData" :rules="formRules" ref="formRef" label-width="100px" > <el-form-item label="名称" prop="name"> <el-input v-model="formData.name"></el-input> </el-form-item> <el-form-item label="状态" prop="status"> <el-switch v-model="formData.status" active-text="启用" inactive-text="禁用" ></el-switch> </el-form-item> <!-- 可在此处添加更多字段 --> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false">取 消</el-button> <el-button type="primary" @click="submitForm" >确 定</el-button> </div> </el-dialog> </div> </template> <script> // 预留API请求函数位置(实际项目需实现) const api = { // 查询数据 fetchData: (params) => { console.log('API请求: 查询数据', params); // 实际实现示例: // return axios.get('/api/data', { params }); return Promise.resolve({ data: [], total: 0 }); }, // 创建数据 createData: (data) => { console.log('API请求: 创建数据', data); // return axios.post('/api/data', data); return Promise.resolve(); }, // 更新数据 updateData: (id, data) => { console.log('API请求: 更新数据', id, data); // return axios.put(`/api/data/${id}`, data); return Promise.resolve(); }, // 删除数据 deleteData: (id) => { console.log('API请求: 删除数据', id); // return axios.delete(`/api/data/${id}`); return Promise.resolve(); } }; export default { data() { return { // 表格数据 tableData: [], loading: false, // 搜索条件 searchQuery: { name: '' }, // 分页配置 pagination: { currentPage: 1, pageSize: 10, total: 0 }, // 对话框控制 dialogVisible: false, dialogType: 'create', // 'create' 或 'edit' // 表单数据 formData: { id: null, name: '', status: true }, // 表单验证规则 formRules: { name: [ { required: true, message: '请输入名称', trigger: 'blur' }, { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' } ] } }; }, mounted() { this.fetchTableData(); }, methods: { // 获取表格数据 async fetchTableData() { this.loading = true; try { const params = { ...this.searchQuery, page: this.pagination.currentPage, size: this.pagination.pageSize }; const response = await api.fetchData(params); this.tableData = response.data; this.pagination.total = response.total; } catch (error) { console.error('获取数据失败:', error); this.$message.error('获取数据失败'); } finally { this.loading = false; } }, // 打开创建对话框 openCreateDialog() { this.dialogType = 'create'; this.formData = { id: null, name: '', status: true }; this.dialogVisible = true; // 重置表单验证 if (this.$refs.formRef) { this.$refs.formRef.clearValidate(); } }, // 打开编辑对话框 openEditDialog(row) { this.dialogType = 'edit'; this.formData = { ...row }; // 深拷贝当前行数据 this.dialogVisible = true; if (this.$refs.formRef) { this.$refs.formRef.clearValidate(); } }, // 提交表单(创建/更新) async submitForm() { this.$refs.formRef.validate(async (valid) => { if (!valid) return; try { if (this.dialogType === 'create') { await api.createData(this.formData); this.$message.success('创建成功'); } else { await api.updateData(this.formData.id, this.formData); this.$message.success('更新成功'); } this.dialogVisible = false; this.fetchTableData(); // 刷新表格 } catch (error) { console.error('操作失败:', error); this.$message.error('操作失败'); } }); }, // 删除数据 handleDelete(row) { this.$confirm('确定删除该记录?', '警告', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(async () => { try { await api.deleteData(row.id); this.$message.success('删除成功'); this.fetchTableData(); // 刷新表格 } catch (error) { console.error('删除失败:', error); this.$message.error('删除失败'); } }).catch(() => {}); }, // 搜索 handleSearch() { this.pagination.currentPage = 1; // 重置到第一页 this.fetchTableData(); }, // 重置搜索 resetSearch() { this.searchQuery = { name: '' }; this.handleSearch(); }, // 分页大小变化 handleSizeChange(size) { this.pagination.pageSize = size; this.fetchTableData(); }, // 页码变化 handlePageChange(page) { this.pagination.currentPage = page; this.fetchTableData(); } } }; </script> <style scoped> .crud-container { padding: 20px; background: #fff; border-radius: 4px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); } .search-form { margin-bottom: 20px; } .action-buttons { margin-bottom: 20px; } .el-pagination { margin-top: 20px; text-align: right; } </style> ``` ### 核心功能说明 1. **CRUD 操作实现**: - **查询**:通过搜索表单和分页组件实现数据筛选 - **新增**:点击"新增"按钮打开对话框填写表单 - **编辑**:点击行操作列的"编辑"按钮 - **删除**:点击行操作列的"删除"按钮(带确认提示) 2. **预留 API 接口**: ```javascript // 在 script 部分预留的 API 接口 const api = { fetchData: (params) => { /* 实际请求实现 */ }, createData: (data) => { /* 实际请求实现 */ }, updateData: (id, data) => { /* 实际请求实现 */ }, deleteData: (id) => { /* 实际请求实现 */ } }; ``` 3. **关键组件**: - `el-table`:展示数据表格,支持加载状态 - `el-form`:用于搜索和创建/编辑表单 - `el-dialog`:模态对话框实现表单提交 - `el-pagination`:分页控制组件 - `el-loading`:数据加载状态指示器 ### 最佳实践建议 1. **API 集成**: ```javascript // 实际项目中的 API 实现示例(使用 axios) import axios from 'axios'; const api = { fetchData: (params) => axios.get('/api/items', { params }), createData: (data) => axios.post('/api/items', data), updateData: (id, data) => axios.put(`/api/items/${id}`, data), deleteData: (id) => axios.delete(`/api/items/${id}`) }; ``` 2. **表单验证增强**: ```javascript formRules: { email: [ { type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur' } ], phone: [ { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' } ] } ``` 3. **性能优化**: - 使用防抖处理搜索输入 - 添加表格数据缓存 - 实现批量操作功能 4. **安全增强**: - 敏感操作增加二次确认 - 表单提交时防止重复点击 - 后端返回数据的严格校验 ### 扩展建议 1. 添加 **批量删除** 功能(配合表格选择列) 2. 实现 **导出 Excel** 功能 3. 增加 **列自定义显示** 功能 4. 添加 **操作日志** 记录 5. 实现 **数据权限** 控制 此实现提供了完整的 CRUD 界面框架和 API 集成方案,您只需替换 API 实现部分即可对接真实后端服务。Element UI组件化设计使得界面维护和功能扩展都非常便捷[^1]。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值