大家好,我是 前端架构师 - 大卫。
更多优质内容请关注微信公众号 @程序员大卫。
初心为助前端人🚀,进阶路上共星辰✨,
您的点赞与关注❤️,是我笔耕不辍的灯💡。
背景
公司有一个较老的项目,使用的是 Vue2 搭配 Element UI(1.4.13)
。 在这个版本中,Form 表单的校验方法不会返回 Promise,因此需要自己封装。 另外,上传组件(Upload)不像 Input、Select 那样能直接触发校验,因此也需要单独处理。
1. 封装表单校验 Promise
为了解决 Form 表单校验不返回 Promise 的问题,可以封装一个 validateForm
方法,使其返回 Promise,便于在 async/await
语法下使用。
html
<!-- 示例表单 -->
<template>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="pass">
<el-input
type="password"
v-model="form.pass"
auto-complete="off"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm">提交</el-button>
</el-form-item>
</el-form>
</template>
<script>
import validateForm from "./utils/validateForm";
export default {
data() {
return {
form: { username: "", pass: "" },
rules: {
username: [
{ required: true, message: "请输入用户名", trigger: "blur" },
],
pass: [{ required: true, message: "请输入密码", trigger: "blur" }],
},
};
},
methods: {
async submitForm() {
try {
await validateForm(this.$refs.form);
console.log("验证通过");
} catch (_e) {
console.log(_e); // ['请输入用户名', '请输入密码']
}
},
},
};
</script>
js
// 封装的 Promise 校验方法
export function validateForm(form) {
return new Promise((resolve, reject) => {
const getErrorMsg = () =>
form.fields
.filter((item) => item.validateMessage)
.map((item) => item.validateMessage);
form.validate((valid) => {
if (valid) {
resolve();
} else {
reject(getErrorMsg());
}
});
});
}
2. 附件上传的校验
对于上传组件,直接调用 validateField
方法即可。 不过需要注意以下几点:
- 字段名 upload 要一致
data.form.upload
、data.rules.upload
以及 el-form-item
的 prop="upload"
必须保持一致。
- 校验类型必须是数组
rules.upload.type
必须写成 "array"
,因为上传的文件列表是一个数组。
- 事件监听要完整
只监听 onChange
不够,因为它不会捕捉附件移除事件。必须同时监听 onSuccess
和 onRemove
,在文件列表变化时手动触发校验。
html
<template>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="附件上传" prop="upload">
<el-upload
action="https://jsonplaceholder.typicode.com/posts/"
:on-success="onSuccess"
:on-remove="onRemove"
:file-list="form.fileList"
>
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">
只能上传jpg/png文件,且不超过500kb
</div>
</el-upload>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
form: { upload: [] },
rules: {
upload: [
{
type: "array", // 注意这里的类型是 array
required: true,
message: "请输入附件",
trigger: "change",
},
],
},
};
},
mounted() {
this.$refs.form.validate((valid) => {
console.log("valid", valid);
});
},
methods: {
updateFileList(fileList) {
this.form.upload = fileList;
this.$refs.form.validateField("upload");
},
onRemove(_file, fileList) {
this.updateFileList(fileList);
},
onSuccess(_response, _file, fileList) {
this.updateFileList(fileList);
},
},
};
</script>
总结
在 Element UI(1.4.13)
中:
- 表单校验需要自己封装 Promise 方法,方便在
async/await
里使用。 - 上传组件要注意字段名、校验类型一致,并在文件上传或删除时手动调用
validateField
。
这样就能比较优雅地解决老版本 Element UI 在表单校验和上传校验上的问题。