使VueJS data()和v-bind中的动态设置对象值具有反应性:同步表单

时间:2019-12-21 14:27:14

标签: javascript vue.js javascript-objects vue-reactivity

因此,我正在构建一个动态表单生成器,该表单生成器基于在data()中创建为form: {}的对象生成表单,然后在beforeMount()中设置绑定的问题键/值对到使用v-bind.sync生成表单的子组件。

我希望能够看到页面上form: {}内的键/值对的更改,但是由于键/值对是动态生成的,因此它们不是被动的。

登录this.form时,我可以看到对对象值的更改,但是我想我缺少使它们在页面上刷新的函数:

Screenshot of page with console logs

父组件,其中设置了空表单对象:

<template lang="html">
  <div>
    <DynamicForm
      v-bind.sync="form"
      :questions="questions"
      :onSubmit="onSubmit"
    >
      <template slot="buttons">
        <b-button
          type="submit"
          block
        >
          Submit
        </b-button>
      </template>
    </DynamicForm>

    <div class="form-output">
      {{form}}
    </div>
  </div>
</template>

<script>
export default {
  // ...
  data(){
    return {
      form: {},
// questions normally loaded via http request, set here in data for example's sake
      questions: [
        {
          "type": "TEXT",
          "label": "Name",
          "model": "name"
        },
        {
          "type": "NUMBER",
          "label": "Age",
          "model": "age"
        }
      ]
    }
  },
  beforeMount(){
    let questionArray = this.questions

    for(var i = 0; i < questionArray.length; i++){
      this.form[questionArray[i].model] = questionArray[i].defaultValue ? questionArray[i].defaultValue : ''
    }
  },
  // ...
}

DynamicForm组件发出的信号如下:

<template lang="html">
    <template v-for="question in questions">
        <b-form-input
          :v-model="question.model"
          @input="formInput(question.model, $event)"
        >
        </b-form-input>
    </template>
  </b-form>
<script>
export default {
  // ...
  props: {
    questions: Array,
    onSubmit: Function
  },
  methods: {
    formInput(key, value) {
      console.log(`Key: ${key}, Value: ${value}`)
      this.$emit(`update:${key}`, value)
    },
  },
  // ...
}
</script>

Click here to view this project on GitHub

1 个答案:

答案 0 :(得分:0)

此答案是由Michael Levy在评论中英勇张贴的Vue reactivity doc link提供的。

为了使动态生成的表单内容具有反应性,我们必须使用Vue.set设置表单键值对,在组件内将其别名为this.$set(object, key, value)

使用beforeMount()而非Vue.set的新this.form[questionArray[i].model] = questionArray[i].value

  beforeMount(){
    let questionArray = this.questions

    for(var i = 0; i < questionArray.length; i++){
      var valueToSet = questionArray[i].defaultValue ? questionArray[i].defaultValue : ''

      this.$set(this.form, questionArray[i].model, valueToSet)
    }
  },