项目场景:
昨天公司让写一个增删改查页面,使用的是Antd组件库,其中包含图片的上传组件,按照form表单文档里,抄写了示例,unpload组件可以使用v-decorator绑定fileList,但公司要求传入后端的是上传后的url地址,当然也可以使用这种方式直接绑定fileList,在提交表单后再重新将拿到的url地址再传递给后端。
<a-upload
v-decorator="[
'upload',
{
valuePropName: 'fileList',
getValueFromEvent: normFile,
},
]"
name="logo"
action="/upload.do"
list-type="picture"
>
<a-button> <a-icon type="upload" /> Click to upload </a-button>
</a-upload>
不过一开始看组件时,直接使用了上传图片并在列表中显示缩略图的a-upload组件实例代码,也就有了后面我遇见这个bug的开始…
控制台报错:
当我将上图示例代码直接粘贴至form表单中,因为打算在上传成功后handleChange方法里,直接将后端返回的url传递给我的imgUrl字段,但一直报错如下:
Warning: You cannot set a form field before rendering a field associated with the value. You can use getFieldDecorator(id, options) instead v-decorator="[id, options]" to register it before render.
警告:在呈现与该值关联的字段之前,不能设置表单字段。你可以使用getFieldDecorator(id, options)代替v-decorator="[id, options]"来在渲染前注册它。
原因分析:
查找了很久的原因才发现,使用Form表单时使用表单setFieldsValue时,有的字段设置了,但Form里不存在这个field。也就是说我赋值的时候,根本不存在imgUrl字段,从log打印果然发现字段结果是undefined,其实在antd的form表单创建form对象时,是通过 this.$form.createForm(),并搭配着 v-decorator,才使得注册了对象里的每个字段,而我在upload字段中并没有使用 v-decorator,所以导致了报错。
解决方案:
解决方案呢有两种
第一种可以直接在Dom节点中直接创建该字段
mounted() {
this.form.getFieldDecorator('imgurl', {
initialValue: '',
rules: [{ required: true, message: '请输入封面图片地址!' }],
});
},
第二种方式呢,也可以直接在a-upload组件中添加一个隐藏的input框
<!-- 添加隐藏的input输入框,v-decorator来关联imgurl字段 -->
<a-input type="hidden" v-decorator="[ 'imgurl', {initialValue: '', rules: [{ required: true, message: '请输入封面图片地址!' }] }]" />
以上两种方式任选,都可以实现在form中设置imgUrl字段,最后再在上传文件成功时,重新赋值imgUrl,在提交时form表单就可以看到这个字段及值啦。
// 文件上传
handleChange (info) {
const { file } = info;
// 判断文件状态
switch (file.status)
{
case 'uploading':
// 上传中,不做处理
break;
case 'done':
// 上传成功
if (file.response && file.response.code === 200)
{
// 确保在使用setFieldsValue之前,表单字段已经被注册
this.form.setFieldsValue({
imgurl: file.response.data.url,
});
this.$message.success('上传成功');
} else
{
// 上传失败,但服务器返回了响应
this.$message.error('上传失败,请重试');
}
break;
case 'error':
// 上传失败,没有从服务器得到响应
this.$message.error('上传失败,请检查网络连接');
break;
default:
// 其他状态,不做处理
break;
}
this.fileList = info.fileList;
},
当然,也可以直接在提交时通过上传文件的this.fileList 取值上传,只不过那样的话,校验规则还得重新写相关代码,所以还是不用这种方式了。
以上均为个人的菜鸟总结,记录自己免得下次踩坑还是不知道解决方法吧