Vue array.splice从列表中删除错误的项目

时间:2017-08-12 21:30:03

标签: javascript arrays vuejs2 splice array-splice

我有一个列表,我正在使用for循环来遍历它。结构如下所示:

salesLists: { 
  1: [ [], [], [] ]
  2: [ [], [] ]
}

和html:

<div v-for="(saleLists, index) in salesLists">
    <my-comp v-for="(item, i) in saleLists" :key="i" :index="parseInt(i)+1"></my-comp>
</div>

现在,我正在尝试从salesLists[1]数组中删除项目。我有一个按钮和@click="removeForm"

removeForm(e) {
        var index = parseInt(e.target.getAttribute('data-index')) - 1 // = 2
        var client = e.target.getAttribute('data-client')             // = 1
        //Vue.delete(this.salesLists[client], index);
        this.salesLists[client].splice(index, 1)
        this.$forceUpdate()
}

然而,它删除了它,因为我没有指定任何键,它只是空数组(我假设),它不是从DOM中删除正确的元素。它删除了2的索引,但由于它是v-for循环遍历项目,并且count减少了,它只删除了最后一项。

克服此问题的正确方法是什么? :/

这是一个小提琴:https://jsfiddle.net/8rvfz40n/ 尝试为每个输入字段写入不同的值并删除中间的值,您将看到它将删除最后一个

3 个答案:

答案 0 :(得分:4)

<div v-for="(saleLists, index) in salesLists">
    <my-comp v-for="(item, i) in saleLists" :key="i" :index="parseInt(i)+1"></my-comp>
</div>

使用索引作为键是问题,当您从中间删除项目时,丢失的索引是最后一个。

就我而言,我找到的解决方案是添加一个独特的&#34; Hash&#34;对于项目,如ID,但如果项目是新闻,则ID为空。

我使用的哈希是一个时间戳:

Hash: new Date().getTime()

然后:

 <div v-for="(saleLists, index) in salesLists">
     <my-comp v-for="(item, i) in saleLists" :key="item.Hash" :index="parseInt(i)+1"></my-comp>
 </div>

答案 1 :(得分:1)

这个让我觉得很多人绊倒了。

我在vue论坛上写了一个回答  在https://forum.vuejs.org/t/solved-array-of-components-wrong-after-element-remove/11866/3

  

所以问题是这个

     

你有一个数组[rec1,rec2,rec3]

     

该数组的键是0,1,2

     

如果删除索引为1的项目,则会得到一个值为[rec1的数组],   rec3],但键是[0,1],因为数组不跳过   删除后的索引。一旦你在模板中绘制它,   由于您没有定义键,因此组件看到的更改是   键或索引2丢失,这是最后一项,所以它   删除它。

要解决这个问题,您需要找到一种不同的方法来确保您定位目标项目

https://jsfiddle.net/8rvfz40n/2/

在您的情况下,使用项list而不是索引i将删除预期的项目

<div id="app">
  <div v-for="lists in xLists">
    <my-comp v-for="(list, i) in lists" :list="list"></my-comp>
  </div>
</div>

我应该提到另一个选择是以某种方式将唯一键存储在数组中,但正如您可以想象的那样,这可能更难维护

答案 2 :(得分:0)

您的问题实际上非常简单:您在第一个循环中丢失了xLists中对象键的引用。如果您存储对象键并将其作为道具传递,您将保留该引用:

<div v-for="(saleLists, index) in salesLists">
    <!-- index will refer to the object key -->
    <my-comp v-for="(item, i) in saleLists" :key="i" :index="i+1" :sales-list-index=":index"></my-comp>
</div>

您可以简单地检索prop salesListIndex并将其用作指向对象中正确嵌套数组的键。目前尚不清楚实际示例中的组件是如何编写的,而是参考您的小提琴(我使用了字母键,以便您可以判断它是对象键还是数组键,但实现方式如此)是完全相同的):

&#13;
&#13;
Vue.component('my-comp', {
  props: ['index', 'value', 'listKey'],
  template: `
  	<div>
    	<p>xListsKey: {{ listKey }}, index: {{ index }}</p>
    	<input :value="value" /> 
      <button :data-index="index" @click="remove">del </button>
    </div>
  `,

  methods: {
    remove(e) {
      var index = e.target.getAttribute('data-index');
      this.$parent.xLists[this.listKey].splice(index, 1)
    }
  }
})

new Vue({
  el: '#app',
  data: {
    xLists: {
      'aa': [
        ['lorem'],
        ['ipsum'],
        ['dolor']
      ],
      'bb': [
        ['foo'],
        ['bar']
      ]
    }
  }
})
&#13;
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <div v-for="(lists, listKey) in xLists" :key="listKey">
    <my-comp v-for="(list, i) in lists" :key="i" :index="i" :value="list" :list-key="listKey"></my-comp>
  </div>
</div>
&#13;
&#13;
&#13;