更新
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方法仅将属性复制为普通对象,而没有可观察的属性。这在这里讨论过:
答案 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)"
/>