Number

This directive is used for looping. Consider the following example -

			<ul>
				<li v-for="n in 10">{ { n }}</li>
			</ul>
		

So v-for is used on an element. If the v-for can iterate n times, it will create n number of same element. In the above example n is the variable in which we want to store each item. By specifing integer it will start iterating from 1 and will continue until the integer number comes and iterate.

Array

You can also provide an array. Consider the following --

			data: {
				names : ['Santanu', 'Atanu', 'Sumita', 'Aloke']
			}
			<ul>
				<li v-for="name in names">{ { name }}</li>
			</ul>
		

You can also have an array of object. Consider the following --

			data:{
				names : ['Santanu', 'Atanu', 'Sumita', 'Aloke'],
				Students : [
					{
						name : 'Santanu Bera',
						roll : 20
					},
					{
						name : 'Manik Sen',
						roll : 10
					}
				]
			}

			<ul>
				<li v-for="student in Students">
					Name : { { student.name }}, Roll No : { { student.roll }}
				</li>
			</ul>
		

Instead of using { { }} brackets, you can use v-text or v-html depending on your test and requirements. The above example can be replaced with the following -

		<li v-for="student in Students" 
			v-html="'Name :' + student.name + ', Roll No : ' + student.roll ">
		</li>
		

Parent Scope

Inside v-for blocks we have full access to parent scope properties. v-for also supports an optional second argument for the index of the current item.

			var example2 = new Vue({
			  el: '#example-2',
			  data: {
			    parentMessage: 'Parent',
			    items: [
			      { message: 'Foo' },
			      { message: 'Bar' }
			    ]
			  }
			});

			<ul id="example-2">
			  <li v-for="(item, index) in items">
			    { { parentMessage }} - { { index }} - { { item.message }}
			  </li>
			</ul>
		

of

We are using in operator within the v-for syntax. But we can also use of operator instead of in operator. And that will make it closer to Pure JS syntax. But there's no different between these two. It's only user's taste of choice.

			<div v-for="item of items"></div>
		

Object

You can use object too.

			<ul>
				<li v-for="item in Students[0]">{ { item }}</li>
			</ul>
		

You can also provide key as the second argument. In the following example, the first argument is value and the second argument is key.

		<ul>
			<li v-for="(theValue, theKey) in Students[0]">
				{ { theKey }} : { { theValue }}
			</li>
		</ul>
		

You can also provide the index as the third argument -

		<ul>
			<li v-for="(theValue, theKey, i) in Students[0]">
				{ { i }}. { { theKey }} : { { theValue }}
			</li>
		</ul>
		

Key

It is always recomended to use key attribute with the element whenever possible. Because internally how Vue works, using key will make it render the element efficiently and correctly.

A key is the unique string to identify element or component.

			<ul>
				<li v-for='(item, index) in items' :key="index">{ { item }}</li>
			</ul>
		

Mutation Methods

Sometimes you want to change the array dynamically and also update the rendering when you are using v-for. Well, Vue does take cares of all the thing. You just update the array and vue dynamically and instantly will update the DOM according to the updated array. Consider the following example -

			data : {
				items : ['Pear', 'Date', 'Coconut'],
				writeItem : ""
			},
			methods:{
				addItem:function(){
					if(this.writeItem!="")
						this.items.push(this.writeItem);
					this.writeItem = "";
				}
			}
			
			<input type="text" v-model="writeItem">
			<button type="button" v-on:click="addItem"></button>
			<ul>
				<li v-for='(item, index) in items' :key="index">{ {  item }}</li>
			</ul>
		

The above code will output the following -

In the above demo you can see how it works. Everytime you push an item to the array, Vue updates the DOM. Pretty cool. You can do much more than this.

The above example shows the mutation method push. But there are other function which you can also apply. Like pop(), shift(), unshift(), slice(), sort(), reverse() etc.

Non Mutation Methods

There are other methods that doesn't update the original array. Rather, the take the copy of original array and return a new array. For example, slice() method. When working with non-mutating methods, you can replace the old array with the new one.

			this.items = example1.items.filter(function (item) {
			  return item.message.match(/Foo/)
			})
		

In the above example, we are returning a new array and assigning it to. You might think this will cause Vue to throw away the existing DOM and re-render the entire list - luckily, that is not the case. Vue implements some smart heuristics to maximize DOM element reuse.

Caveats

When working with v-for there are certain thing you should remember.

Direct Modification of Array

When you directly set an item with the index, e.g. this.items[indexOfItem] = newValue; Vue cannot track the update in the array and you won't see any change. So avoid modify the array directly.

Always use method like push(), slice() etc to update the array. Or, you can go with the following -

Vue.set()

It takes three argument - target, key and value. And returns the value that has been set. This method set a property on an object. If the object is reactive, ensure the property is created as a reactive property and trigger view updates. This is primarily used to get around the limitation that Vue cannot detect property additions.

			Vue.set(target, key, value);
		

We generaly always update the array using methods, there's no situation when we need to modify the array using index way or neither do we need to update the length directly. That's a bad idea. But for Object type in JS, we generally update object using the syntax like obj[key] = value;. But due to limitatio of JS, Vue cannot detect the change, that's why Vue.set() is used to set a new key to the object so that Vue can update the DOM accordingly.

			var vm = new Vue({
			  data: {
			    a: 1 // The property a is reactive
			  }
			});
		

What if you want to another property to data object from inside the Vue instance or outside the vue whatever. Doing it like the following?

			vm.b = 2 //The property b is not reactive
		

The above will surely add the key b to the data, but it won't be reactive. You can also directly access it using vm.b and it will return 2, but if you do vm.$data, you won't see any property called b. So this not the proper way to assign a new property to data object. Infact there's no way. Because the following won't work properly -

			Vue.set(vm.$data, "name", "Santanu");
		

Try the above code in the console it will output error. Vue won't like it. Because Vue doesn't allow root instance(vm) or data property (vm.$data) to be passed in the method Vue.set(). It can take any object except this two.

As Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object using the Vue.set(object, key, value) method. For example, given:

			var vm = new Vue({
			  data: {
			    userProfile: {
			      name: 'Anika'
			    }
			  }
			})
		

You could add a new age property to the nested userProfile object with:

			Vue.set(vm.userProfile, 'age', 27);
		

vm.$set()

You can also use the vm.$set instance method, which is an alias for the global Vue.set:

			vm.$set(this.userProfile, 'age', 27);
		

Vue.delete()

What if you want to delete an object instead of adding. Using a delete operator? Well, once again, Vue cannot detect it and cannot update the DOM accordingly. That's why similarly to Vue.set(), Vue provides Vue.delete() to delete a key on an object.

			Vue.delete(target, key);
		

The above methoed deletes a property on an object. If the object is reactive, ensure the deletion triggers view updates. This is primarily used to get around the limitation that Vue cannot detect property deletions, but you should rarely need to use it.

In the above example, target is the target object on which you want to perform the deletion and key is the key that exists in that object.

The target object cannot be a Vue instance, or the root data object of a Vue instance.

vm.$delete

This is just an alias of Vue.delete() method.

Directly Assigning a Length

Also don't assign the length property directly like this.items.length = 100;

You might already know that if you assign a length to an array that is less than the array's actual length, JS will trancate the array.

			let arr = ['Apple', 'Banana', 'Guava', 'Pear', 'Date', 'Coconut'];
			arr.length = 3;
			log(arr); // ['Apple', 'Banana', 'Guava'];
		

But if you do it for an array that is reactive, Vue won't detect it that the array has changed. To get around with this problem you can use method splice(). The above deletion operation is same as the following -

			vm.items.splice(newLength);
		

Now the Vue will update the DOM according to the new change in the array.

Assign The Whole Object

Sometimes you may want to assign a number of new properties to an existing object, for example using Object.assign() or _.extend(). In such cases, you should create a fresh object with properties from both objects. So instead of:

			Object.assign(this.userProfile, {
			  age: 27,
			  favoriteColor: 'Vue Green'
			});
		

You would add new, reactive properties with:

			this.userProfile = Object.assign({}, this.userProfile, {
			  age: 27,
			  favoriteColor: 'Vue Green'
			});
		

Template

Sometimes you may want to render multiple block of element using v-for. You can do this using div as a wrapper like this -

			<ul>
				<div v-for='(item, index) in items' :key="index">
					<li>{ { item }}</li>	
					<li class="divider"></li>
				</div>
			</ul>
		

This is fine but not logical. In the DOM, the ul element will contain div and inside it li element. Which is not standard and may not work properly in certain situation. For these kind of scinario, you can use template tag. This tag is built in tag comes with Vue.js. The above example can be replaced with the following -

			<ul>
				<template v-for='(item, index) in items' :key="index">
					<li>{ { item }}</li>	
					<li class="divider"></li>
				</template>
			</ul>
		

Now if you look in the DOM, the Vue removes the template element. It doesn't render this element. Which is more convenient.

V-IF

Sometimes you want to conditionally render the element. But some learner may get confused with the usage of v-if along with v-for. Consider the following example -

			<li v-for="(item, index) in items" :key="index" v-if="age>18"></li>
		

Now the question is? which one of the following is true?

Learners get confused at first. The correct answer is the second one. v-if will run on each iteration and check if it's true. If it is, then Vue will render the element, otherwise v-for will continue with the next iteration.

			<li v-for="todo in todos" v-if="!todo.isComplete">
			  { { todo }}
			</li>
		

Okay, what if you want to achieve the first one where you want to iterate the v-for only if the condition is true?

The answer is template tag. You can wrap the whole v-for block within the template tag with the v-if condition.

		<template v-if="age>18">
			<ul>
				<li v-for="(item, index) in  items" :key="index">{ { item }}</li>
			</ul>
		</template>
		

Component

You can use v-for on a component directly just like the normal element. In this case using key is must in the new version of Vue.

			<my-component
			  v-for="(item, index) in items"
			  v-bind:item="item"
			  v-bind:index="index"
			  v-bind:key="item.id"
			></my-component>