Объект изменения Vue в массиве и реактивность срабатывания
Как я могу вызвать обновление при изменении части объекта, найденного по индексу в массиве?
Документы показывают, как изменить значение массива:
Vue.set(example1.items, indexOfItem, newValue)
или же
example1.items.splice(indexOfItem, 1, newValue)
Но как изменить значение свойства объекта в массиве, не меняя остальную часть объекта?
Следующее работает для обновления свойства, но Vue не реагирует на изменение, пока что-то еще не инициирует обновление.
example1.items[indexOfItem].some_object_property = false
Ответы
Ответ 1
Пока вы вызываете set() один раз, чтобы установить объект (с тем свойством, которое вы собираетесь обновлять) в массиве, Vue будет реагировать на изменения свойств объекта. Вот пример, который имеет один массив объектов, инициализированных в наших данных приложения, и еще один массив объектов, установленных вручную (с Vue.set()) при монтировании. Нажатие кнопки обновляет свойство на одном объекте в каждом из этих массивов, а Vue реагирует. Обратите внимание, что вызов set(), который происходит в mount(), действительно может произойти в любое время.
https://codepen.io/jordan-kalosal/pen/VrwjoR
new Vue({
el: "#app",
data: {
arr: [
{
property: 'OBJ1 Prop'
},
{
property: 'OBJ2 Prop'
}
],
setLater: false
},
mounted() {
this.$set(this, 'setLater', [
{
property: 'setLater OBJ1 Prop'
},
{
property: 'setLater OBJ2 Prop'
}
])
},
methods: {
_updateObjProps() {
this.arr[0].property = (new Date()).toString();
this.setLater[0].property = (new Date()).toString();
}
}
})
Ответ 2
Вы можете обновить под-свойство в элементе массива с помощью this.$set()
. Например, чтобы увеличить субсвойство x
в первых двух элементах массива (создавая вспомогательное свойство, если оно не существует):
methods: {
update() {
this.$set(this.arr[0].foo, 'x', (this.arr[0].foo.x || 0) + 100)
this.$set(this.arr[1].foo, 'x', (this.arr[1].foo.x || 0) + 100)
}
}
new Vue({
el: '#app',
data() {
return {
arr: [
{
foo: {
x: 100,
y: 200
}
},
{
foo: {
/* x does not exist here initially */
y: 400
}
}
]
};
},
methods: {
update() {
this.$set(this.arr[0].foo, 'x', (this.arr[0].foo.x || 0) + 100)
this.$set(this.arr[1].foo, 'x', (this.arr[1].foo.x || 0) + 100)
}
}
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<div id="app">
<button @click="update">Update</button>
<p>arr[0]: {{ arr[0] }}</p>
<p>arr[1]: {{ arr[1] }}</p>
</div>
Ответ 3
Вот еще один демонстрационный пример, который, я думаю, дает хорошую иллюстрацию реактивности объектов внутри массива. Попробуйте это здесь: https://codepen.io/antoniandre/pen/ZdjwKG
JS
new Vue({
el: "#app",
data: {
array: []
},
methods: {
addTimeProp() {
this.array.forEach(item => {
this.$set(item, 'time', null)
})
},
updateObjectProp() {
this.array.forEach(item => {
item.time = (new Date()).toString()
})
}
},
created () {
this.array.push({ name: 'today' }, { name: 'tomorrow' })
}
})
HTML: PUG
#app
h1 Reactivity of objects inside an array
h2 Content of the array
pre {{ array }}
button(@click="array.push({ name: 'another day' })") Add another object
button(@click="addTimeProp") Add 'time' property
button(@click="updateObjectProp") Update 'time' property