1

So I've been using vuejs for a few months and I couldn't understand what is happening here. I did this I modified the vuejs code in list rendering for a bit

html:

<ul id="array-with-index" class="demo">
  <li v-for="(item, index) of items" :key = "index">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
    <button @click = "removeItem(index)"> remove </button>
  </li>
  
  <button @click = "addItem"> add </button>
</ul>

And this is the code in javascript:

Vue.createApp({
  data() {
    return {
      parentMessage: 'Parent',
      items: [{ message: 'Foo' }, { message: 'Bar' }]
    }
  },
  methods: {
    removeItem(index){
      this.items.splice(index, 1); 
    },
    addItem(){
      this.items.push({message: "hello"}); 
    }
  }
}).mount('#array-with-index')

Every time I pushed a few new item in items and decided I would delete the item before the last item. It deletes the last item instead. Why does this happen? and how can I remedy this?

8
  • can you try for...in instead of for...of Commented Sep 6, 2021 at 8:02
  • @DrPlague In VueJS, we mostly use [ for in operator ] instead of [ for of operator ]. Try to filter the array and put the filtered into the items. Or you can use compute property to do the same thing and return the filtered items. [ Compute property is a reactive function and that means if one of its dependencies change, it'll change as well. Otherwise, it won't [ Optimization manner ] Commented Sep 6, 2021 at 8:06
  • the same result nothing changed. @KarmaBlackshaw Commented Sep 6, 2021 at 8:08
  • 1
    It is working as expected. CODESANDBOX Commented Sep 6, 2021 at 8:09
  • 1
    Even though It is working, It is highly recommended not to use index for the unique keys. More info Commented Sep 6, 2021 at 8:21

2 Answers 2

1

Vue keeps tabs of the items in the list by using the :key attribute. In your code, you are using the index of the array (items) to keep track of the elements in items. Any operation like, splice, or slice, alters the index of the elements in that arrays. This causes the keys to be mismatched. In other to remedy this, assign a unique keys to element in the items like this

Vue.createApp({
  data() {
    return {
      parentMessage: 'Parent',
      items: [{ message: 'Foo', id:'uniqueId1' }, { message: 'Bar', id, 'uniqueId2'  }]
    }
  },
  methods: {
    removeItem(id){
      // find the index of the id
      let index = this.items.findIndex((element) => element.id == id )
      this.items.splice(index, 1); 
    },
    addItem(){
      let id = generateIdFunc() // a function that generate random id
      this.items.push({message: "hello", id}); 
    }
  }
}).mount('#array-with-index')

In your component you can now have it like so

<ul id="array-with-index" class="demo">
  <li v-for="(item, index) of items" :key = "items.id">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
    <button @click = "removeItem(index)"> remove </button>
  </li>
  
  <button @click = "addItem"> add </button>
</ul>
enter code here
Sign up to request clarification or add additional context in comments.

Comments

0

You should use for/in instead of for/of

<ul id="array-with-index" class="demo">
  <li v-for="(item, index) of items" :key = "index">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
    <button @click = "removeItem(index)"> remove </button>
  </li>

  <button @click = "addItem"> add </button>
</ul>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.