最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why v-model doesn't work with an array and v-for loop? - Stack Overflow

programmeradmin1浏览0评论

I got a custom select component, it works with a simple variable, but when used with v-for it won't work:

/

<select2 v-for="item, index in samples" v-model="item" ></select2>
data : { samples : [0, 0, 0]}

This works:

<select2 v-model="sample"></select2>
data : { sample : 0}  

what am I missing here?

I got a custom select component, it works with a simple variable, but when used with v-for it won't work:

https://jsfiddle.net/7gjkbhy3/19/

<select2 v-for="item, index in samples" v-model="item" ></select2>
data : { samples : [0, 0, 0]}

This works:

<select2 v-model="sample"></select2>
data : { sample : 0}  

what am I missing here?

Share Improve this question edited Mar 25, 2017 at 14:30 Hashem Qolami 99.5k27 gold badges155 silver badges165 bronze badges asked Mar 25, 2017 at 8:06 AngeloCAngeloC 3,52310 gold badges32 silver badges52 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 12

v-model and v-for do NOT go together well if v-model is used to an iteration alias w/ a primitive value.

The Vue warns:

You are binding v-model directly to a v-for iteration alias. This will not be able to modify the v-for source array because writing to the alias is like modifying a function local variable. Consider using an array of objects and use v-model on an object property instead.

Therefore using an array of objects each of which has a property for the select value would solve the issue:

WORKING EXAMPLE.

<select2 v-for="item, index in samples" v-model="item.value" ></select2>
new Vue({
     el: '#app',
     data: {
         sample: 0,
         samples : [{ value: 0 }, { value: 0 }, { value: 0 }]
     }
 })

I don't like the idea of having to change the view model to resolve a framework design constraint. What if the model is to be sent to your backend via an API call? It would involve an additional step of having to mutate the model.

My solution to this was to create a Vue component that boxes the value at each array index into an object that can be referenced within it's slot. It then reacts to the data-changing by updating the array at the specified index via a watcher.

boxed-value.vue

<template>
    <div>
        <slot v-bind:item="boxedItem"></slot>
    </div>
</template>

<script>
    export default {
        props: {
            array: {
                type: Array,
                required: true
            },
            index: {
                type: Number,
                required: true
            }
        },
        data() {
            var data = {
                boxedItem: {value: this.array[this.index]}
            }

            return data
        },
        created(){

        },
        watch: {
            'boxedItem.value': function(oldValue, newValue) {
                // console.log('Array item at index ' + this.index + ' value changed from ' + oldValue + ' to ' + newValue)
                this.array[this.index] = newValue
            }
        }
    }
</script>

Example

<div v-for="(name, index) in primitiveValues" :key="index">
    <boxed-value :array="primitiveValues" :index="index">
        <template slot-scope="{item}">
            <el-input v-model="item.value"></el-input>
        </template>
    </boxed-value>
</div>
发布评论

评论列表(0)

  1. 暂无评论