el-form-item结合v-if使用遇到的问题

5,583 阅读2分钟

这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战

问题

最近在写一个管理平台,使用vue + elementUI,有个表单需求,里面有个表单项需要动态切换。

比如一个单选框,如果选了选项1,则下面展示表单项1,如果选了选项2,则下面展示表单项2。

代码如下:

  <el-form :model="form" :rules="formRule" ref="form">
    <el-form-item prop="status">
      <el-radio v-model="form.status" :label="true">key1</el-radio>
      <el-radio v-model="form.status" :label="false">key2</el-radio>
    </el-form-item>
    <div v-if="form.status">
      <el-form-item prop="key1" label="key1:">
        <el-input v-model="form.key1"></el-input>
      </el-form-item>
    </div>
    <div v-else>
      <el-form-item prop="key2" label="key2:">
        <el-input v-model="form.key2"></el-input>
      </el-form-item>
    </div>
    <el-button @click="reset">重置</el-button>
  </el-form>
export default {
  name: 'HelloWorld',
  data () {
    return {
      form: {
        key1: 'val1',
        key2: 'val2',
        status: true
      },
      formRule: {
        key1: [{
          required: true, trigger: 'blur', message: '请填写'
        }],
        key2: [{
          required: true, trigger: 'blur', message: '请填写'
        }]
      }
    }
  },
  methods: {
    reset () {
      this.$refs.form.resetFields()
    }
  }
}

效果如下:

  • 当你选择key1的时候,下面展示的是key1,input的value是val1
  • 当你选择key2的时候,下面展示的是key2,input的value是val2

GIF 2022-1-15 17-11-47.gif

正常是没有问题。

但是如果这是需要我清空表单的时候,调用了this.$refs.form.resetFields()的方法。

GIF 2022-1-15 17-23-12.gif

可以看当我点重置后,key2的value变成了val1。 直接重置成key1的value值了,这是有问题的。

分析

为什么会出现这样的问题呢? 难道是跟v-if有关?

苦思无果,只能去看看el-form的代码了。

el-formresetFields方法会调用el-form-itemresetField方法。

image.png

el-form-item会在mounted钩子函数的时候记录initialValue(初始值)

image.png

然后重置的时候会使用这个初始值去重置。

image.png

正常看下来这流程没有问题啊。

但是你仔细想一想,虽然我们用了v-if来切换,但是我们用到都是同一个组件,el-form-item

对于相同的组件或者元素,如果key没有设置的时候,vue是会进行复用的。

image.png

vue会做缓存,即使你使用了v-if,但是对于相同的组件,切换的时候组件的createdmounted等钩子函数只会触发第一次,之后就不会触发。

然后el-form-item是在mounted钩子函数里面记录初始值,所以就导致记录不到第二个表单项的初始值。

解决

那该怎么处理?

vue的key属性,这时候就可以派上用场了。

image.png

所以我们可以给组件设置各自的key,让它们在v-if切换的时候,触发组件的生命周期钩子。

    <div v-if="form.status">
      <el-form-item prop="key1" label="key1:" key="key1">
        <el-input v-model="form.key1"></el-input>
      </el-form-item>
    </div>
    <div v-else>
      <el-form-item prop="key2" label="key2:" key="key2">
        <el-input v-model="form.key2"></el-input>
      </el-form-item>
    </div>

GIF 2022-1-17 10-32-48.gif

可以看到点了重置之后是正常的了。

大家如果有其它方法也可以在评论区交流讨论。