快速更改会擦除对象属性

时间:2018-09-13 09:46:48

标签: javascript vue.js

我有一个使用服务器端验证和强制的表单。

在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);

        }
    },

*更新:*

我想我知道现在发生了什么。

  1. 字段A触发change()
  2. 数据已发送以进行验证
  3. 用户开始在字段B中输入
  4. 返回验证的数据。并设置在this.instance上。
  5. Vue跳过字段B,因为它不在this.reached
  6. 但是this.instance正在更新和重绘。

字段B可能在输入中输入了文本,但尚未将其添加到this.instance,因为它尚未触发change()。因此,this.instance是根据没有值的字段B重绘的,这将更新输入并擦除其中可能存在的所有内容。

2 个答案:

答案 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时不会擦除任何内容。