30 Days of Vue

List Rendering with v-for

 

This post is part of the series 30 Days of Vue.

In this series, we're starting from the very basics and walk through everything you need to know to get started with Vue. If you've ever wanted to learn Vue, this is the place to start!

List Rendering with v-for

Today we're going to work through how the v-for directive can be used to dynamically render a list of elements based on a data source.

Today's article is a summarized and simpler version of the article List Rendering and Vue's v-for directive, which was originally posted on CSS-Tricks and the freeCodeCamp blogs.

List Rendering

List rendering is one of the most commonly used practices in front-end web development. Dynamic list rendering allows us to present a series of similarly grouped information in a concise and friendly format to the user. In almost every web application we use, we can see lists of content in numerous areas of the app.

Take a website like Twitter for example. When logged in and in the main index route, we’re presented with a view similar to this:

Twitter uses lists of elements everywhere. Here we have a list of trends, a list of tweets, and a list of potential followers
Twitter uses lists of elements everywhere. Here we have a list of trends, a list of tweets, and a list of potential followers

On the homepage, we’ve become accustomed to seeing a list of trends, a list of tweets, a list of potential followers, etc. The content displayed in these lists depends on a multitude of factors—our Twitter history, who we follow, our likes, etc. As a result, it's probably safe to say all this data is dynamic.

Though this data is dynamically obtained, the way this data is shown remains the same. This is in part due to rendering lists of reusable elements.

If we wanted to render a list of elements in Vue, the first thing that should come to mind to accomplish this is the v-for directive.

The v-for directive

The v-for directive is used to render a list of items based on a data source. The directive can be used on a template element and requires a specific syntax along the lines of item in items, where items is a data collection and item is an alias for every element that is being iterated upon:

Let’s see a very simple example of this in practice. Assume we have a template currently displaying a list of static numbers in ascending order:

<html>
  <head>
    <link rel="stylesheet" href="./styles.css" />
  </head>

  <body>
    <div id="app">
      <ul>
        <li>1</li>
        <li>10</li>
        <li>100</li>
        <li>1000</li>
        <li>10000</li>
      </ul>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script src="./main.js"></script>
  </body>
</html>

Live version - https://30dofv-staticlist.surge.sh

If we had the list of numbers available to us in a collection (e.g. an array) in our Vue instance:

new Vue({
  el: '#app',
  data: {
    numbers: [1, 10, 100, 1000, 10000],
  },
});

We could avoid repeating the <li> element in the template and instead have the v-for directive do the work for us. Since numbers is the array we’ll be iterating over, number would be an appropriate alias to use. We’ll add the v-for directive on the element we want repeated - the <li> element:

<html>
  <head>
    <link rel="stylesheet" href="./styles.css" />
  </head>

  <body>
    <div id="app">
      <ul>
        <li v-for="number in numbers">{{ number }}</li>
      </ul>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script src="./main.js"></script>
  </body>
</html>

We’re using the Mustache syntax to bind the number alias on to the text content of the repeated element since we’re interested in only displaying the number values from the array.

At this moment, the v-for directive would display the list of static numbers from the numbers data array:

Live version - https://30dofv-vfor.surge.sh

In addition to helping make the template be more D.R.Y, the v-for directive is helpful since our application is now entirely dynamic. Regardless of how the numbers array changes over time, our set up will always render all the numbers in the collection in the same markup we expect.

The key attribute

It’s common practice to specify a key attribute for every iterated element within a rendered v-for list. This is because Vue uses the key attribute to create unique bindings for each node’s identity.

If there were any dynamic UI changes to our list (e.g. the numbers list gets randomly reshuffled), Vue will (by default) opt towards changing data within each element instead of moving the DOM elements accordingly. This won’t be an issue in most cases. However, in certain instances where our v-for list depends on DOM state and/or child component state, this can cause some unintended behavior.

Let’s see an example of this. Instead of rendering just the number content within each element, let’s render both the number value and an input element for each number in the numbers array.

<html>
  <head>
    <link rel="stylesheet" href="./styles.css" />
  </head>

  <body>
    <div id="app">
      <ul>
        <li v-for="number in numbers">
          <p>{{ number }}</p>
          <input placeholder="type something..."/>
        </li>
      </ul>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script src="./main.js"></script>
  </body>
</html>

Assume we wanted to introduce another new feature into our app. This feature would involve allowing the user to shuffle the list of numbers randomly. To do this, we’ll first include a “Shuffle!” button in our HTML template right after the unordered list:

<html>
  <head>
    <link rel="stylesheet" href="./styles.css" />
  </head>

  <body>
    <div id="app">
      <ul>
        <li v-for="number in numbers">
          <p>{{ number }}</p>
          <input placeholder="type something..."/>
        </li>
      </ul>
      <button @click="shuffle">Shuffle!</button>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script
      src="https://cdn.jsdelivr.net/npm/lodash/lodash.js">
    </script>
    <script src="./main.js"></script>
  </body>
</html>

We’ve attached a click event listener on the button element to call a shuffle method when triggered. We've also introduced a new <script> tag in our template that has a src pointing to a CDN of the Lodash utility library. We'll be using Lodash to help create the shuffle functionality in our list.

In our Vue instance; we’ll create the shuffle method responsible for randomly shuffling the numbers collection in the instance. To avoid having to create a random shuffle of our own, we’ll use the Lodash _.shuffle method to achieve this:

The entire source code for this tutorial series can be found in the GitHub repo, which includes all the styles and code samples.

If at any point you feel stuck, have further questions, feel free to reach out to us by:

Get started now

Join us on our 30-day journey in Vue. Join thousands of other professional Vue developers and learn one of the most powerful web application development frameworks available today.

No spam ever. Easy to unsubscribe.