ElementUI Form resetFields


前言

在一次结合v-if/v-elseresetFields结合使用reset之后值不正常,看完源码提了issue,然后被告知答案原来就在vue文档里,打脸打脸,因此记录一次不看文档,并且出问题不第一时间找文档的教训。

结论

  1. 凡事先从文档下手,用element-ui不是光看element-ui的文档,还要看vue文档
  2. Form组件resetFieldsdata值没什么关系,只跟Form-Item创建时的初始值有关。
  3. 使用v-if/v-else时,要先确定组件是需要重新生成(用 key 管理可复用的元素),还是可以直接替换(新组件会使用旧组件的初始值,事实上这里新旧是同一个组件更改了属性)。
  4. 只有含有prop属性,并且当前存在的组件才会reset
  5. 如果Form组件不是一开始就创建,可以用nextTick等待Form/Form-Item第一次创建完再resetFields。(这个其实跟组件没多大关系)

事故现场

https://jsfiddle.net/s5ar1un3…

上面代码切换组件后,执行resetFields重置值,结果重置的值为别的组件绑定的初始值。

事故原因

Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。

也就是说使用v-if/v-else时,虽然看似是多个组件切换,但实际上是1个组件切换了自身的属性。但问题的关键是,切换了vue的属性,element-ui添加的属性比如初始值并没有换。

解决

https://jsfiddle.net/s5ar1un3…

Vue 为你提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 key 属性即可。

在事故现场上加上key值绑定。用 key 管理可复用的元素

resetFields过程

form.vue

created() {
      this.$on('el.form.addField', (field) => {
        if (field) {
          this.fields.push(field);
        }
      }
      
      this.$on('el.form.removeField', (field) => {
        if (field.prop) {
          this.fields.splice(this.fields.indexOf(field), 1);
        }

      });
}

resetFields() {
        ...
        
        this.fields.forEach(field => {
          field.resetField();
        });
      },

form-item.vue

    mounted() {
        if (this.prop) {
            this.dispatch('ElForm', 'el.form.addField', [this]);
            ...
            
            let initialValue = this.fieldValue;
            
            ...
            
            Object.defineProperty(this, 'initialValue', {
              value: initialValue
            });
            ...
        }
    }

    beforeDestroy() {
      this.dispatch('ElForm', 'el.form.removeField', [this]);
    }

    resetField() {
        ...

        this.validateDisabled = true;
        if (Array.isArray(value)) {
          prop.o[prop.k] = [].concat(this.initialValue);
        } else {
          prop.o[prop.k] = this.initialValue;
        }
    }
  1. Formcreated阶段创建监听,保存下当前Form-Item
  2. Form-Itemmounted判断是否存在prop属性,如果有,设置好初始值。
  3. Form组件resetFields实际上是保存当前注册上来的子组件Form-ItemresetField方法。
  4. Form-ItemresetField方法重新赋值为this.initialValue。(之前事故原因就是组件属性更新initialValue值是不会变的)

参考

https://cn.vuejs.org/v2/guide…

https://github.com/ElemeFE/el…

http://element-cn.eleme.io/#/…


发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>