Vuejs 和 Vue.set() ,更新数组

我刚来维耶斯,做了点东西,但我不知道是不是简单正确的方法。

我想要的

我希望在一个数组中的一些日期,并更新他们的事件。一开始我试过 Vue. set,但没成功。现在更改数组项之后:

this.items[index] = val;
this.items.push();

I push() nothing to the array and it will update.. But sometimes the last item will be hidden, somehow... I think this solution is a bit hacky, how can I make it stable?

简单的代码在这里:

new Vue({
el: '#app',
data: {
f: 'DD-MM-YYYY',
items: [
"10-03-2017",
"12-03-2017"
]
},
methods: {
    

cha: function(index, item, what, count) {
console.log(item + " index > " + index);
val = moment(this.items[index], this.f).add(count, what).format(this.f);
this.items[index] = val;
this.items.push();
console.log("arr length:  " + this.items.length);
}
}
})
ul {
list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.11/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<div id="app">
<ul>
<li v-for="(index, item) in items">
<br><br>
<button v-on:click="cha(index, item, 'day', -1)">
- day</button>
{{ item }}
<button v-on:click="cha(index, item, 'day', 1)">
+ day</button>
<br><br>
</li>
</ul>
</div>

242219 次浏览

VueJS can't pickup your changes to the state if you manipulate arrays like this.

As explained in Common Beginner Gotchas, you should use array methods like push, splice or whatever and never modify the indexes like this a[2] = 2 nor the .length property of an array.

new Vue({
el: '#app',
data: {
f: 'DD-MM-YYYY',
items: [
"10-03-2017",
"12-03-2017"
]
},
methods: {


cha: function(index, item, what, count) {
console.log(item + " index > " + index);
val = moment(this.items[index], this.f).add(count, what).format(this.f);


this.items.$set(index, val)
console.log("arr length:  " + this.items.length);
}
}
})
ul {
list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.11/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<div id="app">
<ul>
<li v-for="(index, item) in items">
<br><br>
<button v-on:click="cha(index, item, 'day', -1)">
- day</button> \{\{ item }}
<button v-on:click="cha(index, item, 'day', 1)">
+ day</button>
<br><br>
</li>
</ul>
</div>

EDIT 2

  • For all object changes that need reactivity use Vue.set(object, prop, value)
  • For array mutations, you can look at the currently supported list here

EDIT 1

For vuex you will want to do Vue.set(state.object, key, value)


Original

So just for others who come to this question. It appears at some point in Vue 2.* they removed this.items.$set(index, val) in favor of this.$set(this.items, index, val).

Splice is still available and here is a link to array mutation methods available in vue link.

As stated before - VueJS simply can't track those operations(array elements assignment). All operations that are tracked by VueJS with array are here. But I'll copy them once again:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

During development, you face a problem - how to live with that :).

push(), pop(), shift(), unshift(), sort() and reverse() are pretty plain and help you in some cases but the main focus lies within the splice(), which allows you effectively modify the array that would be tracked by VueJs. So I can share some of the approaches, that are used the most working with arrays.

You need to replace Item in Array:

// note - findIndex might be replaced with some(), filter(), forEach()
// or any other function/approach if you need
// additional browser support, or you might use a polyfill
const index = this.values.findIndex(item => {
return (replacementItem.id === item.id)
})
this.values.splice(index, 1, replacementItem)

Note: if you just need to modify an item field - you can do it just by:

this.values[index].itemField = newItemFieldValue

And this would be tracked by VueJS as the item(Object) fields would be tracked.

You need to empty the array:

this.values.splice(0, this.values.length)

Actually you can do much more with this function splice() - w3schools link You can add multiple records, delete multiple records, etc.

Vue.set() and Vue.delete()

Vue.set() and Vue.delete() might be used for adding field to your UI version of data. For example, you need some additional calculated data or flags within your objects. You can do this for your objects, or list of objects(in the loop):

 Vue.set(plan, 'editEnabled', true) //(or this.$set)

And send edited data back to the back-end in the same format doing this before the Axios call:

 Vue.delete(plan, 'editEnabled') //(or this.$delete)

One alternative - and more lightweight approach to your problem - might be, just editing the array temporarily and then assigning the whole array back to your variable. Because as Vue does not watch individual items it will watch the whole variable being updated.

So you this should work as well:

var tempArray[];


tempArray = this.items;


tempArray[targetPosition]  = value;


this.items = tempArray;

This then should also update your DOM.

Observe object and array reactivity here:

https://v2.vuejs.org/v2/guide/reactivity.html