Vue JS 2

时间:2018-04-11 02:55:24

标签: javascript arrays vuejs2

更新

Vue JS 3将正确处理:https://blog.cloudboost.io/reactivity-in-vue-js-2-vs-vue-js-3-dcdd0728dcdf

问题:

我有一个vue组件,如下所示:

子comp.vue

<template>
    <div>
        <input type="text" class="form-control" v-model="textA">
        <input type="text" class="form-control" v-model="textB">
        <input type="text" class="form-control" v-model="textC">
    </div>
</template>
<script>
    export default {
        props: {
            textA: {
                type: Number,
                required: false
            },
            textB: {
                type: Number,
                required: false
            },
            textC: {
                type: Number,
                required: false
            }
        }
    }
</script>

我有一个如下所示的父组件:

布局comp.vue

<template>
    <div>
        <button @click="addItem">Add</button>
        <ul>
            <li v-for="listItem in listItems"
                :key="listItem.id">
                <sub-comp 
                      :textA="listItem.item.textA"
                      :textB="listItem.item.textB"
                      :textC="listItem.item.textC"
                />
            </li>
        </ul>
    </div>
</template>
import subComp from '../sub-comp.vue'
export default {
    components: {
        subComp
    },
    data() {
        return {
            listItems: []
        }
    },
    methods: {
        addItem: function () {
            var item = {
                         textA: 5,
                         textB: 100,
                         textC: 200
                       }
            if (!item) {
                return
            }
            this.length += 1;
            this.listItems.push({
                id: length++,
                item: item
            });
        }
    } 
</script>

问题是,无论我做什么来编辑文本框,数组都不会被更改,即使被动数据显示它已更改。例如,它将始终为

 { 
     textA: 5,
     textB: 100, 
     textC: 200 
 }

即使我更改了textB:333,listItems数组仍然显示textB:100。这是因为:

https://vuejs.org/v2/guide/list.html#Caveats

  

由于JavaScript的限制,Vue无法检测到数组的以下更改

问题:

我想知道如何更新阵列?我还希望在离开文本框时使用@blur事件进行更改。我想看看有什么方法可以做到。

我读了这些材料:

https://codingexplained.com/coding/front-end/vue-js/array-change-detection https://vuejs.org/v2/guide/list.html

但似乎我的例子有点复杂,因为它有索引关联,而且数组有复杂的对象。

更新4/12/2018

在我的addItem()中找到了:

item = this.conditionItems[this.conditionItems.length - 1].item);

item = JSON.parse(JSON.stringify(this.conditionItems[this.conditionItems.length - 1].item));

我在想下面答案中的同步修饰符导致问题,因为它复制了所有项目。但事实并非如此。我正在复制一个vue对象(包括可观察的属性),这导致它发生。 JSON解析和JSON stringify方法仅将属性复制为普通对象,而没有可观察的属性。这在这里讨论过:

https://github.com/vuejs/Discussion/issues/292

1 个答案:

答案 0 :(得分:1)

问题是道具从父母到孩子的一个方向流动。

在子级中使用v-model设置值不会影响父级数据。

Vue有一个更轻松地更新父数据的快捷方式。它被称为.sync modifier

这是怎么做的。

在sub-comp.vue

<template>
    <div>
        <input type="text" class="form-control" :value="textA" @input="$emit('update:textA', $event.target.value)" >
        <input type="text" class="form-control" :value="textB" @input="$emit('update:textB', $event.target.value)">
        <input type="text" class="form-control" :value="textC" @input="$emit('update:textC', $event.target.value)">
    </div>
</template>

<script>
export default {
  // remains the same
}
</script>

添加道具时添加.sync

             <sub-comp 
                  :textA.sync="listItem.item.textA" // this will have the same effect of v-on:update:textA="listItem.item.textA = $event"
                  :textB.sync="listItem.item.textB"
                  :textC.sync="listItem.item.textC"
            />

更新:

如果您有反应性问题,请不要使用.sync,添加自定义事件并使用$ set

             <sub-comp 
                  :textA="listItem.item.textA" v-on:update:textA="$set('listItem.item','textA', $event)"
            />