DEV Community

Cover image for Vue Academy #4: v-for directive
Code Oz
Code Oz

Posted on • Edited on

Vue Academy #4: v-for directive

Welcome to the new vue academy ! It will be a list of lot of article on vue! I have 2.5 years of experience in this and I can teach a few thing about this !

With vue you can use some directives, today we will see v-for in details !

What is ?

v-for is a directive use to render a list of items based on an array or an object.

<template>
<div>
    <div
        v-for="item in toto"
        :key="item"
        >
        {{ item }}
    </div>
</div>
</template>
<script>
import Vue from "vue"

export default Vue.extend({
    data() {
        return {
            toto: [ 'first', 'second', 'third' ],
        }
    },
})
</script>
Enter fullscreen mode Exit fullscreen mode

In this component we will have three div as below 👇

first
second
third
Enter fullscreen mode Exit fullscreen mode

You can also get the current index of the iterated item

    <div
        v-for="(item, index) in toto"
        :key="item"
        >
        {{ item }} {{ index }}
    </div>
Enter fullscreen mode Exit fullscreen mode

It works also with object ! If we replace toto: [ 'first', 'second', 'third' ] by an object like toto: { a: 1, b: 2, c: 3 }

We have 👇

1
2
3
Enter fullscreen mode Exit fullscreen mode

We can also access to the current key !

    <div
        v-for="(item, attribute) in toto"
        :key="item"
        >
        {{ item }} {{ attribute }}
    </div>
Enter fullscreen mode Exit fullscreen mode

The key attribute

With the example above, you can ask what is this :key value?

In vue, :key is used in all components, if the key is changed, the component will be reload (destroy and created hook will be triggered). It a simply way to reload properly a component !

In general you don't need to handle this attribute, but in the v-for, key is MANDATORY !

And why ?

To give Vue a hint so that it can track each node’s identity, and thus reuse and reorder existing elements, you need to provide a unique key attribute for each item.

I advise you to never use index as key attribute, always use a unique ID. The answer is not complicated to illustrate, imagine again an array with 1000 items, you delete the second item, so the length of the iterated array will be changed, and all index of all items will changed, so all components will be reload !

If you use a unique id by item, and you delete the second item, the other component will be not reload since all of the key is not changed !

v-for with v-if

You should NEVER use v-for with v-if, since when they exist on the same node, v-for has a higher priority than v-if. That means the v-if will be run on each iteration of the loop separately !

Let's go through an example !

<template>
<div>
    <div
        v-for="item in numberList"
        v-if="isEven(item)"
        :key="item"
        >
        {{ item }}
    </div>
</div>
</template>
<script>
import Vue from "vue"

export default Vue.extend({
    data() {
        return {
            numberList: [ 1, 2, 3, 4, 5, 6 ],
        }
    },
    methods: {
        isEven(item) {
            return item % 2 === 1
        },
    },
})
</script>
Enter fullscreen mode Exit fullscreen mode

For each iteration we will execute the isEven function !

How to avoid this?

Two solutions based on the context:

First

We need to filter some value in your array !

Use computed property and iterate it !

<template>
<div>
    <div
        v-for="evenItem in evenList"
        :key="evenItem"
        >
        {{ evenItem }}
    </div>
</div>
</template>
<script>
import Vue from "vue"

export default Vue.extend({
    data() {
        return {
            numberList: [ 1, 2, 3, 4, 5, 6 ],
        }
    },
    computed: {
        evenList() {
            return this.numberList.filter(item => this.isEven(item))
        }
    },
    methods: {
        isEven(item) {
            return item % 2 === 0
        },
    },
})
</script>
Enter fullscreen mode Exit fullscreen mode

Here we filter the array before iterate it ! We don't need to use v-if !

Second

I need to display the items only if the array size is equal to 5 for exemple.

You can just add an other balise that will wrap the v-for, it will contain the v-if !

<template>
<div>
    <div v-if="numberList.length === 5" >
       <div
           v-for="item in numberList"
           :key="item"
           >
           {{ item }}
       </div>
    </div>
</div>
</template>
Enter fullscreen mode Exit fullscreen mode

Conclusion

v-for is used to show array or object keys, you need to always use a unique id as key attribute.

Never use v-for with v-if, depending on the current context you have other possibilities !


I hope you like this reading!

🎁 You can get my new book Underrated skills in javascript, make the difference for FREE if you follow me on Twitter and MP me 😁

Or get it HERE

🎁 MY NEWSLETTER

☕️ You can SUPPORT MY WORKS 🙏

🏃‍♂️ You can follow me on 👇

🕊 Twitter : https://twitter.com/code__oz

👨‍💻 Github: https://github.com/Code-Oz

And you can mark 🔖 this article!

Top comments (4)

Collapse
 
jamesthomson profile image
James Thomson

Small tip. You can use template with v-if/else to avoid unwanted elements in the DOM.

Instead of

<div v-if="numberList.length === 5" >
Enter fullscreen mode Exit fullscreen mode

do this

<template v-if="numberList.length === 5" >
Enter fullscreen mode Exit fullscreen mode
Collapse
 
codeoz profile image
Code Oz

Nice tips James! Totally agree!

Collapse
 
johnatanetges profile image
Johnatan Etges

Hi! I don't get it. Why did you still declare "isEven" method if you just filtered the array in the "computed" declaration?

Tanks in advance.

Collapse
 
codeoz profile image
Code Oz

Hey bro I miss it I just replace it by this.numberList.filter(item => this.isEven(item))! Thank you you rock!