VueJS 2.0 v-model dynamic target inside v-for

2019-04-16 03:39发布

I've got a form with about 10 select elements built from an array in my Vue data.

The array of selectors is empty initially and then an AJAX call populates the array and Vue builds the HTML - I've kept the snippet below simplified just to demonstrate the issue I'm having with v-model

I want to create an object that has all the selected values in it, so I'm trying to use v-model="selected[ selector.name ]" as per the example below. I want to easily be able to ask for selected.make or selected.fuel

Now this works if I initialize the selected property like this:

selected: { make: 'audi', fuel: 'petrol' }

If I leave it blank, like in the example, {}, then it doesn't get updated. I don't want to manually hardcode all the properties of selected, I only want to be listing them once in the server side code that gets sent via AJAX

So am I missing something completely obvious, should I be doing this in a different way?

Maybe a method to find the dropdown that matches a field name and returns the value? Just that doesn't seem like a very Vue thing to do.

var app = new Vue({
	el: '#example',
	data: {
		selectors: [
			{
				name: 'make',
				options: ['audi','bmw']
			},
			{
				name: 'fuel',
				options: ['petrol','diesel']
			}
		],
		selected: {}
	}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.3/vue.js"></script>

<div id="example">

<template v-for="selector in selectors">
  <select v-model="selected[ selector.name ]">
    <option v-for="option in selector.options">{{option}}</option>
  </select>
</template>
  
<p>
  {{selected.make}}
  <br />
  {{selected.fuel}}
</p>
  
</div>

1条回答
等我变得足够好
2楼-- · 2019-04-16 04:27

it's probably becuase you're not setting new keys on an object with this.$set

try:

this.$set(this.selected, 'make', 'audi')

Not using this.$set - alias of Vue.set - will mean Vue doesn't set the new key as reactive, and in turn won't be watching for any updates to it, docs: https://vuejs.org/v2/api/#vm-set

var app = new Vue({
    el: '#example',
    data: {
        selectors: [{
            name: 'make',
            options: ['audi', 'bmw']
        }, {
            name: 'fuel',
            options: ['petrol', 'diesel']
        }],
        selected: null,
    },
    created () {
        // this would happen following your ajax request - but as an example this should suffice
        this.selected = {}
        this.selectors
            .forEach((selector) => {

                this.$set(this.selected, selector.name, '')

            })

    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.3/vue.js"></script>
<div id="example">

    <div v-if="selected">

        <select v-model="selected[selector.name]" v-for="selector in selectors">
            <option :value="option" v-for="option in selector.options">
                {{option}}
            </option>
        </select>

        <p>make: {{selected.make}}<p>
        
        <p>fuel: {{selected.fuel}}</p>
        
        <pre>{{ selected }}</pre>

    </div>

</div>

查看更多
登录 后发表回答