最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Vue array.splice removing wrong item from list - Stack Overflow

programmeradmin5浏览0评论

I have a list and I am using a for loop to loop through it. The structure looks like this:

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

And html:

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

Now, I am trying to remove items from salesLists[1] array. I have a button for that and @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()
}

It removes it, however, as I didn't specify any keys and it's just empty arrays (i assume), it is not removing the right element from the DOM. It removes index of 2, but as it is v-for looping through the item, and count reduces, it only removes the last item in the end.

What is the proper way of overe this issue? :/

Here is a Fiddle: / try writing different values for each input field and removing the middle one, you'll see it will remove the last one

I have a list and I am using a for loop to loop through it. The structure looks like this:

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

And html:

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

Now, I am trying to remove items from salesLists[1] array. I have a button for that and @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()
}

It removes it, however, as I didn't specify any keys and it's just empty arrays (i assume), it is not removing the right element from the DOM. It removes index of 2, but as it is v-for looping through the item, and count reduces, it only removes the last item in the end.

What is the proper way of overe this issue? :/

Here is a Fiddle: https://jsfiddle/8rvfz40n/ try writing different values for each input field and removing the middle one, you'll see it will remove the last one

Share Improve this question edited Aug 12, 2017 at 21:47 senty asked Aug 12, 2017 at 21:30 sentysenty 12.8k29 gold badges140 silver badges267 bronze badges 1
  • And why do you think it removes wrong item? I see that it works properly and removes correct one. jsfiddle/8rvfz40n/1 – dfsq Commented Aug 12, 2017 at 21:57
Add a ment  | 

3 Answers 3

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

The use of the index as key is the problem, when you delete a item from the middle the index that is lost is the last.

In my case the solution that I found is add a unique "Hash" to the items, like an ID, but if the items are news, the ID is null.

The hash that I use is a timestamp:

Hash: new Date().getTime()

And then:

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

this one trips up a lot of people I think.

I've written an answer to this in the vue forum a while back at https://forum.vuejs/t/solved-array-of-ponents-wrong-after-element-remove/11866/3

so the problem is this

you have an array [rec1,rec2,rec3]

the keys for that array are 0, 1, 2

if you remove item at index of 1 you'd get an array with values [rec1, rec3], however the keys would be [0, 1], as the array does not skip the index after you remove it. Once you're in the template drawing it, since you don't have the key defined, the change the ponent sees is that the key or index 2 is missing, which is the last item, so it removes it.

to solve that, you need to find a different way to make sure you're targeting the intended item

https://jsfiddle/8rvfz40n/2/

in your case, using the item list instead of the index i will remove the intended item

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

I should mention that another alternative is to store the unique key somehow inside the array, but as you you can imagine, that can be harder to maintain

Your issue is actually pretty straightforward: you lose the reference to the object key in xLists in your first loop. If you store the object key and pass it on as a prop, you will retain that reference:

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

And you can simply retrieve the prop salesListIndex and use it as the key to point to the correct nested array in your object. It is not clear how the ponent in your actual example is written, but with reference to your fiddle (I have used alphabetical keys so that you can tell if it's an object key or an array key, but implementation-wise it is identical):

Vue.ponent('my-p', {
  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']
      ]
    }
  }
})
<script src="https://unpkg./vue"></script>

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

发布评论

评论列表(0)

  1. 暂无评论