这个问题可以绕得开。
核心思路:在传图成功的同时通过更新绑定值+局部清除验证,来清除上传组件的验证信息。
关键步骤:
1、将 绑定值 与 图片地址参数同步,减少后边的重复操作:将imageUrl与上传组件的对应model同步,可用computed同步这两个值;
2、通过 绑定值+局部清除验证 解决上传控件的验证问题:在上传组件的handleAvatarSuccess函数中(on-success事件绑定的函数),更新this.imageUrl的值之后,需加代码消除验证,可用this.$refs.formRef.clearValidate("这里写上传组件所在的el-form-item的prop");
3、提交表单成功以后,避免再次“被验证”:提交成功要重置表单,但此时表单绑定的model被清空,重置的瞬间会再次触发验证!所以要再次清除表单验证,而且需使用setTimeout来调用this.$refs.formRef..clearValidate(),以避免同时触发导致的清空失败。
接下来的代码需要启动后端才能测出效果,Vue3+Node.js前后端分离,后端关键页面的代码也附上了。
希望能够帮到你,如果有写得不清楚的地方可以追加提问哟~
以下是前端代码:
<template>
<div class="formDiv">
<span class="tit">表单示例</span>
<el-form
ref="formRef"
:model="formM"
:rules="formRule"
label-position="left"
hide-required-asterisk
:status-icon=false
>
<el-form-item prop="name" label="名称" >
<el-input v-model="formM.name" type="input" ></el-input>
</el-form-item>
<el-form-item prop="pic" label="图片" >
<el-upload
class="avatar-uploader"
:action="baseURL + '/formSubmit/picUL'"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm()">提交</el-button>
</el-form-item>
</el-form>
</div>
<div class="hide">{{autoData}}</div>
</template>
<script>
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import { Plus } from '@element-plus/icons-vue';
export default {
name: 'vq2',
components:{Plus},
data(){
return{
imageUrl: ref(''),
formM: {name: "",pic:"",},
formRule:{
name: [
{required: true, message: "名称不能为空", trigger: "change",},
{min: 3, max: 8,
validator(rule, value, callback) {
if (value.length < rule.min || value.length > rule.max) {
callback(new Error(`长度${rule.min}-${rule.max}位`));
} else {callback();}
},},],
pic:[{required: true, message: "上传图片不能为空", trigger: "change",},],},}
},
computed:{
autoData(){
this.formM.pic=this.imageUrl; //自动刷新上传控件的表单绑定值
return this.imageUrl;
}
},
methods:{
handleAvatarSuccess(res, file){
switch (res.code) {
case 111:
this.imageUrl = URL.createObjectURL(file.raw);
ElMessage.success('图片上传成功!')
break;
default:
this.imageUrl = ref('');
ElMessage.error('图片上传失败')
}
this.$refs.formRef.clearValidate("pic"); //消除验证
},
beforeAvatarUpload(file){
const limitSize=2;
const isJPG = /jpeg|jpg|png/.test(file.type);
const isLt = file.size / 1024 / 1024 < limitSize;
!isJPG&&this.showAlertM('图片格式jpeg、jpg、png');
!isLt&&this.showAlertM('图片大小超过'+limitSize+'M');
return isJPG && isLt;
},
submitForm(){ //提交
let form=this.$refs.formRef;
form.validate(async (valid) => {
if (valid) {
let validationAx = await this.$axios({
method: "POST",
url: "/formSubmit/FormDataUL",
data:this.formM,
});
switch (validationAx.data.code) {
case 111:
this.imageUrl = ref('');
form.resetFields(); //提交成功,重置表单
window.setTimeout(()=>{form.clearValidate();},10); //用定时器再清空一遍表单验证,是为了避免重置表单的同时触发验证导致验证清空失败的问题
ElMessage.success('提交成功!');
break;
default:
ElMessage.error('提交失败');
}
} else {
ElMessage.error('验证未通过');
return false
}
})
},
},
}
</script>
<style lang="scss" scoped>
.formDiv{
position: relative;
width: 500px;
padding: 12px 0;
margin: 24px auto ;
border:1px solid rgba(125,125,125,0.1);
border-radius: 7px;
color:dodgerblue;
display: flex;
flex-flow: column nowrap;
justify-content: space-evenly;
align-items: center;
&:hover{
border-color:rgba(125,125,125,0.24);
box-shadow: 1px 2px 1px rgba(125,125,125,0.01);
}
}
.formDiv /deep/ .el-form {
width: 100%;
display: flex;
flex-flow: column nowrap;
justify-content: space-evenly;
align-items: center;
}
.formDiv /deep/ .el-form-item{
margin:0 0 24px;
position: relative;
&:nth-child(2){
position: relative;
left: -20px !important;
}
}
.formDiv /deep/ .el-form-item__label{
color: dodgerblue;
}
.tit{
margin:0 0 12px;
}
.formDiv /deep/ .el-input__inner{
width: 310px;
}
.avatar-uploader /deep/ .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
width: 178px;
height: 178px;
}
.avatar-uploader /deep/ .el-upload:hover {
border-color: var(--el-color-primary);
}
.avatar-uploader /deep/ .el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
.avatar{
display: block;
width: auto;
height: 178px;
}
.el-alert{
position:fixed;
top:24px;
margin: 20px 0 0;
padding: 0 50px;
width: auto;
height:auto;
overflow:visible;
transition: all 0.7s ease-in-out;
}
.el-alert:first-child {
margin: 0;
}
.hide{
visibility: hidden;
}
</style>
以下是后端代码,文件名为formSubmit.js,是路由的内容,需要将这个路由添加到router/index.js才能生效,具体方法我就不赘述了:
const express= require("express");
const router= express.Router();
router.post("/picUL",async (req,res)=>{
let reqData=req.body;
res.send({
code:111,
message:"提交成功",
data:reqData,
});
});
router.post("/FormDataUL",async (req,res)=>{
let reqData=req.body;
res.send({
code:111,
message:"提交成功",
data:reqData,
});
});
module.exports=router;