赞
踩
我这边的需求是修改表单,里面有一项是动态增减表单的,初始值有个问题:我是异步获取的数据,获取到数据之后用setFieldsValue给Form表单赋初值时,一直报错,报错如下:
Warning: You cannot set a form field before rendering a field associated with the value.
警告:在呈现与值关联的字段之前,不能设置窗体字段。
也就是说当我赋初值的时候,Form表单中并没有相关联的字段
created(){
this.form = this.$form.createForm(this);
...then((keys) = > {
this.form.getFieldDecorator('keys', { initialValue: keys, preserve: true });
this.form.setFieldsValue(this.defaultStrategy)
})
}
为了证实是因为异步获取数据导致的问题,我把官方的例子拿过来做了测试,这里放我修改的片段,其他的代码可以自行跳转查看
动态增减表单
运行之后
我在官方的例子代码基础上,用settimeout做了一个异步的模拟
看到这里,相信不运行,你们也都能看出问题了吧,按照这样写的话,肯定先执行beforeCreate的第一行代码,接着执行setFieldsValue中的代码,最后才执行setTimeout中的getFieldDecorator,这样写肯定有问题的。
那有人可能会想,把setFieldsValue那句放到getFieldDecorator后面,实验证明,这样是行不通的,就算不是异步,都是不行的,运行结果如下:
输入框显示了,但是参数没有显示出来,并且控制台报错
Warning: You cannot set a form field before rendering a field associated with the value.
警告:在呈现与值关联的字段之前,不能设置窗体字段。
这个时候,我大胆猜测,在执行setFieldsValue的时候,上一句getFieldDecorator还没执行完,三个输入框,还没有显示出来,所以执行setFieldsValue的时候报错了,报完错之后界面出来了,就这样完美错开。
也就是说我们要保证getFieldDecorator语句执行完之后,再执行setFieldsValue,这样就能解决。那怎么确保getFieldDecorator语句执行完成呢?
先看下官方描述
我很简单地去理解这个东西,也就是说DOM更新的时候就执行nextTick中的方法,那不就刚好是我想要的吗,input渲染出来之后再执行setFieldsValue,那就试试,于是改了代码如下:
运行之后还是不行,跟没有加的效果一样。这种时候换个角度想,nextTick在下次更新循环结束后执行延迟回调,修改数据之后立即使用该方法,于是机智的我,加了个隐藏表单的变量:
运行之后:
居然成功了,真是感动又意外啊。为了找出原因。我把nextTick去掉了,但是又报错,还是上面那个错误,也就是说隐藏变量和nextTick两个都是不可或缺的。
可喜可乐,按照这种方法之后,异步请求数据也不怕出不来初始值了,解决之后我一直在想为什么单独nextTick不能实现,因为它本身就是DOM更新后执行的,回到那个报错,我猜想可能是执行getFieldDecorator的时候,因为异步数据的缘故,虽然从界面上看出现了三个input项,但是可能没有触发Form的更新,而增加一个变量控制样式的隐藏和显示恰好触发了Form的更新,所以用setFieldsValue才不再报错,并且完美显示。
先继续完成功能,这个要去看下antd的源码才能证实我的猜想,或者有大神可以不吝赐教就更好啦!文中有错误好好说,不要喷我,世界和平!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。