This is part 2 of my Basic Vue series. For part 1 click here. Anyways, let's continue
v-for - List Rendering
This code will be a bit long. First, I will share the whole code, after that I will break it down into small chunks.
<script>
// give each todo a unique id
let id = 0
export default {
data() {
return {
newTodo: '',
todos: [
{ id: id++, text: 'Learn HTML' },
{ id: id++, text: 'Learn JavaScript' },
{ id: id++, text: 'Learn Vue' }
]
}
},
methods: {
addTodo() {
this.newTodo = {id: id++, text: this.newTodo}
this.todos.push(this.newTodo)
this.newTodo = ''
},
removeTodo(todo) {
this.todos = this.todos.filter(item => item.id !== todo.id)
}
}
}
</script>
<template>
<form @submit.prevent="addTodo">
<input v-model="newTodo">
<button>Add Todo</button>
</form>
<ul>
<li v-for="todo in todos" :key="todo.id">
{{todo.id}} | {{ todo.text }}
<button @click="removeTodo(todo)">X</button>
</li>
</ul>
</template>
Let's get it into smaller pieces
data() {
return {
newTodo: '',
todos: [
{ id: id++, text: 'Learn HTML' },
{ id: id++, text: 'Learn JavaScript' },
{ id: id++, text: 'Learn Vue' }
]
}
}
To begin with, we need a unique id for each element in the array. So, we create a variable that starts counting from 0 let id = 0
. In Vue (and also React), each element must be tracked by their unique keys (:key=''
).
To add a new todo, we have newTodo: ''
that has an empty string as its initial value. We have an array of objects
(todos:[{}, {}, ...]
), and each object has key values of id and text. We increment id for each object, so we don't need to hard code.
As we keep reading code above from top to bottom, we will see methods, there're two methods in this todo list; addTodo()
and
removeTodo()
addTodo() {
this.newTodo = {id: id++, text: this.newTodo}
this.todos.push(this.newTodo)
this.newTodo = ''
},
With addTodo()
function we access to todos
array and push a new object inside of it. Since todos is an array of objects we must pass in an object when pushing, otherwise it won't work. After pushing we again assign an empty string to this.newTodo
, so the old added value won't remain inside the input. Otherwise, you will see this [object Object].
Now let's remove our todos
removeTodo(todo) {
this.todos = this.todos.filter(item => item.id !== todo.id)
}
We create a function that takes todo
as its parameter. Todo is the one that picks a todo to remove when the X button is clicked. Onto inside of our code block.
First, I will explain the right side of the assignment operator (=
). We filter our todos array. The .filter()
method takes one parameter; item
. The item
parameter loops over each element of the array and compares if the current item
is not equal to todo
(that is clicked by the user). We get a hang of todo
by clicking on the X
button. So, item => item.id !== todo.id
removes the clicked item.
Finally, last chunk of our code:
<template>
<form @submit.prevent="addTodo">
<input v-model="newTodo">
<button>Add Todo</button>
</form>
<ul>
<li v-for="todo in todos" :key="todo.id">
{{todo.id}} | {{ todo.text }}
<button @click="removeTodo(todo)">X</button>
</li>
</ul>
</template>
@submit.prevent
prevents forms from refreshing pages when form is submitted. Then, we've got an input tag that is two-way-binded to newTodo
data. v-model: is responsible for syncing newTodo
data and addTodo()
function. Outside of our form we have got a list
tag.
Here's how v-for works in a list tag:
As you see there's todo in todos
. Yes, we've got todos array, but what is todo? It's a local variable that will be alive only in this
todo
is not accesible outside of todos
array. So, todo
represents each object in todos
array. Since todo
is a local variable, we can name it however we wish, but understandable naming is one of the best practices. For instance, if I had an array of books
, I would have coded it as <li v-for="book in books" :key="book.id"> ... </li>
.
Top comments (0)