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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42807888/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 01:26:28  来源:igfitidea点击:

Vuejs and Vue.set(), update array

javascriptvue.jsmomentjsvuejs2

提问by Johan Hoeksma

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

我是 Vuejs 的新手。做了一些东西,但我不知道这是简单/正确的方法。

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:

我想要数组中的一些日期并在事件上更新它们。首先我尝试了 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?

我不向数组推送()任何东西,它会更新..但有时最后一项会被隐藏,不知何故......我认为这个解决方案有点hacky,我怎样才能使它稳定?

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

采纳答案by Borjante

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

如果您像这样操作数组,VueJS 无法获取您对状态的更改。

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] = 2nor the .length property of an array.

正如Common Beginner Gotchas 中所解释的,你应该使用像 push、splice 或其他的数组方法,并且永远不要修改像这样的索引a[2] = 2或数组的 .length 属性。

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>

回答by Martin Calvert

EDIT 2

编辑 2

  • For allobject changes that need reactivity use Vue.set(object, prop, value)
  • For array mutations, you can look at the currently supported list here
  • 对于需要反应性使用的所有对象更改Vue.set(object, prop, value)
  • 对于数组突变,您可以在此处查看当前支持的列表


EDIT 1

编辑 1

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

对于 vuex 你会想要做 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).

因此,仅适用于提出此问题的其他人。它出现在 Vue 2.* 的某个时候,他们this.items.$set(index, val)为了支持this.$set(this.items, index, val).

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

Splice 仍然可用,这里是 vue link 中可用的数组变异方法的链接

回答by Mykola Korol

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:

如前所述 - VueJS 根本无法跟踪这些操作(数组元素分配)。VueJS 使用数组跟踪的所有操作都在这里。但我会再次复制它们:

  • 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.

push()、pop()、shift()、unshift()、sort() 和 reverse() 非常简单,在某些情况下可以帮助您,但主要焦点在于splice(),它允许您有效地修改数组这将由 VueJs 跟踪。所以我可以分享一些最常用于数组的方法。

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.

这将被 VueJS 跟踪,因为 item(Object) 字段将被跟踪。

You need to empty the array:

您需要清空数组:

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

Actually you can do much morewith this function splice() - w3schools linkYou can add multiple records, delete multiple records, etc.

其实你可以用这个函数做更多的事情splice() - w3schools link你可以添加多条记录,删除多条记录等。

Vue.set() and Vue.delete()

Vue.set() 和 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() 和 Vue.delete() 可用于向 UI 版本的数据添加字段。例如,您的对象中需要一些额外的计算数据或标志。您可以为您的对象或对象列表(在循环中)执行此操作:

 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:

并在 Axios 调用之前以相同的格式将编辑过的数据发送回后端:

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

回答by 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.

一种替代方法 - 更轻量级的方法来解决您的问题 - 可能只是暂时编辑数组,然后将整个数组分配回您的变量。因为 Vue 不监视单个项目,它会监视整个变量的更新。

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.

这也应该更新你的 DOM。