Understanding the v-for Update Strategy

Published on March 13, 2017 by

There is one thing you should be aware of in regards to the v-for directive. When Vue.js updates a list of elements that was rendered with the v-for directive, it uses a so-called “in-place patch” strategy for accomplishing this. What this fancy term means, is that in case the order of the data items changes, it does not move around the DOM elements to reflect this. Instead, it will patch the elements and ensure that each element reflects the new item order, meaning that any string interpolation is refreshed accordingly, for example. In case that didn’t make too much sense, then hopefully it will once you see the example that I have prepared in advance. It outputs a list of persons and allows me to either add a new person to the array or shuffle the elements within the array.

Both of these actions manipulate the persons array. The implementation details of these actions are not important, so you don’t have to pay attention to the JavaScript code unless you are interested in that. As you could see before when I clicked the buttons, Vue.js updates the list whenever I manipulate the array that the v-for directive operates on, and all is good. The important thing to note here, is that it does not move the DOM element, but simply patches its contents. In simple cases, this is all we need, but sometimes this will get us into trouble, as you will see in a moment.

How Vue.js detects these changes to the array is something that we will cover in the next post. For now, you just need to be aware that while this behavior is efficient because it touches the DOM as little as possible, it is not without problems. Since Vue.js reuses the DOM as much as possible, this causes problems in certain scenarios such as when using form controls that rely on the temporary state of the DOM.

Let me show you an example of what I mean, so that it is easier to understand. What I will do, is that I will simply add a text input within the li element, which allows me to keep track of what happens with the DOM.

<li v-for="p in persons">{{ p.name }} (ID: {{ p.id }}) <input type="text"></li>

I will run the code again, and now I have some input fields available to me. What I will do, is that I will type in the name and ID of the person that is rendered within each element.

andy1
abby2
teresa3

Now watch what happens when I click the “shuffle” button. The elements within the array are shuffled and moved around randomly. This is correctly updated in the DOM, because Vue.js recognizes the string interpolation. However, notice how the text inputs were left intact and no longer match with the names and IDs to the left of them! This happens because Vue.js reuses the DOM for each of the li elements as a performance optimization. Clearly this is a problem and can cause real problems in more serious applications than this – problems that can be difficult to debug unless you are aware of this behavior.

So now that we see the problem, let’s see how we can fix it. This can be done by adding a key attribute to each element, which is basically a hint to Vue.js, allowing it to track the identity of each element and thereby reuse and reorder elements correctly. We must bind the key attribute using the v-bind directive, because we need to specify an expression.

Most commonly, we will enter an expression that points to a property on the alias used in the v-for directive, which is p in this example. Since we must provide a unique value, I will use the id property.

<li v-for="p in persons" v-bind:key="p.id">{{ p.name }} (ID: {{ p.id }}) <input type="text"></li>

It is important that we refer to a unique value such that Vue.js can distinguish the elements from each other.

Let’s repeat the test from before, and this time we should see that the input fields are placed and moved correctly in relation to the li elements.

While the default strategy that Vue.js uses results in better performance, you should be careful that you do not face similar problems to what we have just seen. For simple cases where you just use string interpolation to output data, it is perfectly fine to use the default behavior, but as you embed more advanced logic within your v-for block, you should start to consider adding a key attribute to your elements. At the very least you should be aware that bugs like these may occur and that if you see some strange behavior when using the v-for directive, then you should probably try to add a key attribute and see if it resolves the problem. This is really all you need to know; it is not that important to actually understand why this is a problem, as long as you know how to deal with it.

Now it’s time to talk a bit about how Vue.js recognizes when we change an array of items.

Featured

Learn Vue.js today!

Take an online course and become an Vue.js champion!

Here is what you will learn:

  • How to build advanced Vue.js applications (including SPA)
  • How Vue.js works under the hood
  • Communicating with services through HTTP
  • Managing state of large applications with Vuex
  • ... and much more!
Vue.js logo
Author avatar
Bo Andersen

About the Author

I am a back-end web developer with a passion for open source technologies. I have been a PHP developer for many years, and also have experience with Java and Spring Framework. I currently work full time as a lead developer. Apart from that, I also spend time on making online courses, so be sure to check those out!

Leave a Reply

Your e-mail address will not be published.