VueJS动态数据+ v模型

时间:2019-12-07 21:25:25

标签: vue.js

在我的数据对象中,我需要将对象推入名为editions的数组中。

data() {
  return {
    editions: []
  }
}

为此,我将根据一些预定的字段名称动态创建一个表单。这是问题所在。我无法让v模型进行合作。我期待做这样的事情:

<div v-for="n in parseInt(total_number_of_editions)">
  <div v-for="field in edition_fields">
    <input :type="field.type" v-model="editions[n][field.name]" />
  </div>
</div>

但这不起作用。我得到一个TypeError: _vm.editions[n] is undefined。奇怪的是,如果我尝试执行以下操作:v-model="editions[n]" ...可以,但是我没有属性名称。所以我不知道如何editions[n]是不确定的。这就是我要在数据对象中最终得到的结果:

editions: [
  {
    name: "sample name",
    status: "good"
  },
  ... 
]

有人可以建议如何实现这一目标吗?

1 个答案:

答案 0 :(得分:0)

  

但这不起作用。我得到一个TypeError: _vm.editions[n] is undefined

editions最初是一个空数组,因此对于所有editions[n]undefinedn。 Vue本质上就是这样做的:

const editions = []
const n = 1
console.log(editions[n]) // => undefined
  

奇怪的是,如果我尝试使用此方法:v-model="editions[n]" ...有效

editions[n]中使用v-model时,实际上是在索引n处创建具有新值的数组项。 Vue正在做类似的事情:

const editions = []
const n = 2
editions[n] = 'foo'
console.log(editions) // => [ undefined, undefined, "foo" ]

要解决根本问题,请使用长度等于editions的对象数组初始化total_number_of_editions

const newObjArray = n => Array(n)             // create empty array of `n` items
                          .fill({})           // fill the empty holes
                          .map(x => ({...x})) // map the holes into new objects

this.editions = newObjArray(this.total_number_of_editions)

如果total_number_of_editions可以动态更改,请在变量上使用watcher,然后根据新计数更新editions

const newObjArray = n => Array(n).fill({}).map(x => ({...x}))

new Vue({
  el: '#app',
  data() {
    const edition_fields = [
      { type: 'number', name: 'status' },
      { type: 'text', name: 'name' },
    ];
    
    return {
      total_number_of_editions: 5,
      editions: [],
      edition_fields
    }
  },
  watch: {
    total_number_of_editions: {
      handler(total_number_of_editions) {
        const count = parseInt(total_number_of_editions)

        if (count === this.editions.length) {
          // ignore
          
        } else if (count < this.editions.length) {
          this.editions.splice(count)

        } else {
          const newCount = count - this.editions.length
          this.editions.push(...newObjArray(newCount))
        }
      },
      immediate: true,
    }
  }
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.min.js"></script>

<div id="app">
  <label>Number of editions
    <input type="number" min=0 v-model="total_number_of_editions">
  </label>

  <div><pre>total_number_of_editions={{total_number_of_editions}}
editions={{editions}}</pre></div>

  <fieldset v-for="n in parseInt(total_number_of_editions)" :key="n">
    <div v-for="field in edition_fields" :key="field.name+n">
      <label>{{field.name}}{{n-1}}
        <input :type="field.type" v-if="editions[n-1]" v-model="editions[n-1][field.name]" />
      </label>
    </div>
  </fieldset>
</div>