重置表单并随着表单增长轻松维护的最干净方法

时间:2019-05-24 18:00:32

标签: vuejs2

我正在使用VueJS创建输入表单,该表单包含大约10多个输入字段。我有一个重置按钮,单击该按钮可以将表单的值“重置”为空字符串,null或布尔值(我有实际形式的复选框)。

我目前可以正常使用,但是我不禁感到奇怪,一旦我在表单中添加了其他字段,这种方法将很难维护。每次我要添加一个新字段时,我都必须使用该新字段来更新我的重置方法。 *我确实想使事情保持简单,所以我也不想让事情变得过于复杂...因此,对于初级开发人员来说,保持这种方法可能更容易阅读。

这是一个好方法吗?

这是我当前的代码:

  

脚本部分:

..snip...
data() {
    return {
      show: true,
      products: [],
      subjects: [],
      form: {
        product: '',
        subject: ''
      }
    }
},
created() {
    this.getProducts() <--- getting products from an api
    this.getSubjects() < -- getting subjects from an api
    ..snip..
},
  methods: {
    resetForm() {
      this.form = {
        product: '',
        subject: ''
      }
      // Trick to reset/clear native browser form validation state
      this.show = false
      this.$nextTick(() => {
        this.show = true
      })
    }
...snip...
  

模板部分:

<form v-if="show">
..snip..
<label for="product_select_input">Product:</label>
          <select
            id="product_select_input"
            v-model="form.product"
            required
          >
            <option disabled value="">Select</option>
            <option
              v-for="product in products"
              :key="product.product_id"
              :value="product.product_id"
              >{{ product.product_name }}</option
            >
          </select>
..snip..
<button @click.prevent="resetForm">
            Reset Form
          </button>
...snip...
</form>

2 个答案:

答案 0 :(得分:0)

我已经看到许多解决方案,包括 Object.assign(this.$data, this.$options.data.call(this)) 如果您的数据需要为空字符串,则还可以使用for循环来重新创建对象。但是,我喜欢这种解决方案:

    data () {
      return {
       form: this.getEmptyForm()
      }
    },
    methods: {
      getEmptyForm () {
       return {
        product: '',
        subject: ''
       }
      }, 
      resetForm () {
       this.form = this.getEmptyForm()
      }
    }

答案 1 :(得分:0)

我用来重置表单和/或data值的最干净(并且可能是最可靠的)方法是合并初始方法(可通过$options访问) )进入“肮脏” $data状态。

Object.assign(this.$data, this.$options.data.call(this));

说明:

  1. Object.assign作为合并策略(如果可以)。随时使用lodash.mergedeepmerge之类的第三方库进行高级合并。
  2. this.$data引用当前Vue实例dataofficial doc的摘录:

      

    创建实例后,原始数据对象可以作为vm.$data访问。

    这就是为什么即使它是Vue实例,您也不能简单地传递this的原因。

  3. this.$options.data是数据“工厂”,可用于创建初始数据的新副本。

    为此,您需要data defined as a function

    call(this)部分只是一个函数原型,它允许您使用给定的this值(在本例中为Vue实例)调用函数。当您在初始化时从data对象内部引用Vue实例时,尤其需要这样做,例如:

    data() {
      return {
        pageTitle: this.$route.meta.title
      }
    },
    
    // Or, the ES6 equivalent
    data: vm => ({
      pageTitle: vm.$route.meta.title
    })
    

    在这一点上,如果没有给定的this上下文,它将实际上引发异常。

为使此操作更加方便,您可以扩展Vue原型并在需要重置data的任何时间和任何地方开始调用它。

完整演示

Vue.prototype.$resetVueData = function() {
  if (typeof this.$options.data !== 'function') {
    console.warn('No `data` option being specified in this Vue instance.', this);
    return false;
  }

  Object.assign(this.$data, this.$options.data.call(this));
}

new Vue({
  el: '#app',

  data: vm => ({
    show: false,
    products: [],
    subjects: [],
    form: {
      product: '',
      subject: ''
    }
  }),

  methods: {
    resetForm() {
      this.$resetVueData();

      // The rest of your form-resetting logic goes here
      // Like Vuetify's form.resetValidation, or state restoration of complex data
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <pre>{{$data}}</pre>

  <button @click="show = !show">Show/Hide</button>
  <button @click="products.push(Date.now())">Add random product</button>
  <button @click="subjects.push(Date.now() / 2)">Add random subject</button>
  <button @click="form.product = 'Some product'; form.subject = 'Subject1'">Add form data</button>
  <button @click="resetForm">RESET</button>
</div>


建议。我仅出于演示目的和简短原因使用内联值分配。

PPS 这种合并策略会影响整个data,因此,如果您需要定位其中的特定对象,则可以在方法中为目标的键名添加另一个参数,然后合并时,将其与this.$data上的bracket notation一起使用。但是应该有更多的方法来实现这一目标。