ChatGPT解决这个技术问题 Extra ChatGPT

Vuejs and Vue.set(), update array

I'm new to Vuejs. Made something, but I don't know it's the simple / right way.

what I want

I want some dates in an array and update them on a event. First I tried Vue.set, but it dind't work out. Now after changing my array item:

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?

Simple code is here:

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; }



  • {{ item }}


t
tony19

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.


What string do I need to provide as the 'index' ?
@Kokodoko can you clarify what you are trying to do? If it is an array it should be a number for the index. A string would be if you are setting a field on an object.
Ah ok, my IDE insisted it had to be a string, must be a glitch.
Vue.set is not for vuex. And this.$set deprecated.
@MartinCalvert It says "when adding property to object". That is Vue.set's main purpose, not related to only vuex. Deprecation, i read it on the link but now reading again, i don't fully understand it. stackoverflow.com/questions/36671106/…
A
AlexMA

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; }



  • {{ item }}


As said in the docs, $set is just a pretty .splice(). This makes sense because like they say in the docs you should modify the array using it's methods.
Pls don't combine tab indents with space indents, the size of a tab is apparently different on the SE app, making it hard to read your code
In my case the ES6 spread-operator for the push operation does not work proberly with vue
t
tony19

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)

G
Geole

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.


t
tony19

Observe object and array reactivity here:

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