我有一个使用服务器端验证和强制的表单。
在Vue中,表单字段的状态保存在数据对象上名为instance
的对象中。每个字段的值都由instance
的属性表示。
onChange
的任何字段,instance
被发布到API方法,该方法返回验证结果和强制数据集(强制执行诸如在电话号码中添加空格,大写邮政编码等操作)。>
Vue获取响应并遍历强制数据,从而替换instance
的属性。如果用户尚未访问某个字段,那么将跳过该字段(有一个reached
对象,用于跟踪用户将其输入哪些字段)。
我遇到的问题是(从一个字段到下一个字段非常快速地输入数据时)从上一个字段返回强制数据时,当前字段的输入会被清除。
最初,我认为reached
逻辑一定存在问题,并且为用户正在处理的字段返回的null
数据正在覆盖当前输入。但这种情况并非如此;我在日志中看到字段被跳过,但输入仍在清除。
我开始认为这可能是Vue的错误。或者至少是关于Vue如何处理我需要考虑的数据/ dom元素的特定内容。设置instance.foo
会导致instance.bar
重置吗?
//this is called onChange for any field.
change: function(e) {
this.$set(this.instance, e.name, e.value);
this.setReached(e.name);
this.validate(true);
},
validate: function(reachedOnly) {
axios.post(this.validateUrl, this.getFormData(false)).then(response => {
this.allErrors = response.data.errors;
this.setFormData(response.data.values, reachedOnly);
this.fieldNumberValidated = this.fieldNumberReached;
});
},
setFormData: function(data, reachedOnly) {
for (var fieldName in this.fieldNames) {
var value = data[fieldName];
if(reachedOnly && !this.reached[fieldName]){
console.log('skipping - '+fieldName);
continue;
}
if (value && value.date) {
value = value.date.replace(/\.\d+$/,'');
}
this.$set(this.instance,fieldName,value);
}
},
*更新:*
我想我知道现在发生了什么。
this.instance
上。this.reached
中this.instance
正在更新和重绘。 字段B可能在输入中输入了文本,但尚未将其添加到this.instance
,因为它尚未触发change()
。因此,this.instance
是根据没有值的字段B重绘的,这将更新输入并擦除其中可能存在的所有内容。
答案 0 :(得分:1)
这不是一个完整的答案,只是一些想法。
我不确定为什么要清除 字段,但是我想指出您可能遇到的并发问题。如果您为每个按键调用API,则不能保证它们会以正确的顺序响应,这可能是因为您将表单数据设置为旧的验证响应,这会导致您丢失输入的任何文本自从请求被触发以来进入文本框。同样,最好不要向服务器发送过多请求,这是一个好主意。
您至少应该消除API调用的反跳,或者使用blur
而不是change
事件,或者可以实现一些逻辑,以在触发另一个请求之前取消所有未决的验证请求。
您使用this.$set
时是否有任何特定原因?仅在向对象添加属性时才使用它。
最初,我认为到达的逻辑一定存在问题,并且用户正在处理的字段返回的空数据正在覆盖当前输入。但这种情况并非如此;我在日志中看到字段被跳过,但输入仍在清除。
设置数据时最好记录而不是跳过。问题是某些字段已被清除,因此每次设置它们时都要记录日志,这样您就可以确定设置该字段的时间,而不应该设置该字段。
是否可以通过设置
instance.foo
导致instance.bar
重置?
不是我所知道的。如果您可以提供MCVE,这会有所帮助。
答案 1 :(得分:0)
我最终通过在输入字段中包含2个不同的事件解决了这一问题-一个事件input
更新instance
,另一个事件blur
发送验证请求。
change: function(e) {
this.validate(true);
},
input: function(e) {
this.$set(this.instance, e.name, e.value);
},
这可确保instance
的属性始终与其相关的输入字段一致,因此重绘instance
时不会擦除任何内容。