Search code examples
vue.jsv-for

What key to use for v-for when elements have no id?


When using v-for, it is strongly recommended to include a key. Furthermore, as explained here, using the array index as your key doesn't really help.

If your elements have an id property, then that's great - you could just use that as your key. But what about when your elements don't have an id property? What should you use as your key in that scenario?


Solution

  • Better solution

    A better solution would be to use an external library to generate a hashcode from the value of your object and use that as an id. i.e. object-hash

    An example using object-hash

    const hash = objectHash; // this should be the import i.e. require('object-hash');
    
    new Vue({
      el: '#app',
      template: `
      <div>
        <p v-for="item in itemsWithHash" :key="item.key">
          {{item.name}} {{item.lastname}}<br>key: {{ item.key }}
        </p>
      </div>
      `,
      data: () => ({
        items: [
          { name: 'john', lastname: 'doe' },
          { name: 'bob', lastname: 'smith' },
          { name: 'alice', lastname: 'james' }
        ]
      }),
      computed: {
        itemsWithHash() {
          return this.items.map(i => ({ ...i, key: hash(i) }));
        }
      }
    });
    <script src="https://cdn.jsdelivr.net/npm/object-hash@1.3.1/dist/object_hash.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="app"></div>

    OK Solution

    You can use the index of the iteration as a key, but keep in mind that this will not trigger changes on the view if you update the item by index. (Vue uses the key to detect changes, so it wont re-render the template if the key is not updated)

    <div v-for="(item, i) in items" :key="i">
        // some content.
    </div>
    

    Note the example below where mutating the items directly by index does not update the view but prints the change to the console:

    new Vue({
      el: '#app',
      template: `
      <div>
        <p v-for="(item, index) in items" :key="index">
          {{item.name}} {{item.lastname}}<br>index: {{ index }}
          <button @click="changeForMary(index)"> Replace with Mary Smith</button>
        </p>
      </div>
      `,
      data: () => ({
        items: [
          { name: 'john', lastname: 'doe' },
          { name: 'bob', lastname: 'smith' },
          { name: 'alice', lastname: 'james' }
        ]
      }),
      methods: {
        changeForMary(index){
          this.items[index] = { name: 'mary', lastname: 'smith' };
          console.log(`index ${index} changed to ${JSON.stringify(this.items[index], null, '\t')}`);
        }
      }
    });
    <script src="https://cdn.jsdelivr.net/npm/object-hash@1.3.1/dist/object_hash.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="app"></div>