Como iterar sobre itens em Vue.js com V-for
Introdução
Um requisito comum para aplicativos front-end é listar itens. Pode assumir a forma de uma lista de tarefas e sistemas de cartões. O Vue.js suporta a renderização de listas de itens no navegador usando a diretiva interna v-for<
core.
Neste post, vamos explorar como v-for
pode ser usado em aplicações Vue.
Pré-requisitos
Esta postagem pressupõe que você tenha algum conhecimento sobre loops, arrays e objetos em JavaScript. Você pode consultar esta série se estiver começando com JavaScript.
Esta exploração será construída sobre um arquivo HTML que usa uma cópia hospedada CDN (rede de entrega de conteúdo) da estrutura Vue.js:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-for</title>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
new Vue({
el: "#app",
data() {
return {
message: "hello"
}
}
});
</script>
</body>
</html>
Você pode consultar esta postagem se estiver começando com o Vue.js.
Neste ponto, se você carregar este código e visualizar este arquivo em um navegador, verá a mensagem: hello
.
Usando v-for com Range
A diretiva interna v-for
nos permite percorrer os itens.
Podemos usar um intervalo na diretiva v-for
para iterar um número especificado de vezes.
Vamos substituir o conteúdo do nosso <div>
por uma lista não ordenada que repete os itens da lista 15 vezes:
<div id="app">
<ul>
<li v-for="item in 15">{{ item }}</li>
</ul>
</div>
Isso resultará em uma lista não ordenada com números 1
a 15
.
Usando o elemento
A diretiva v-for
aplica-se apenas ao elemento ao qual está anexada. Se vários itens forem repetidos com a diretiva v-for
, devemos agrupar os elementos em um elemento <template>
.
Vamos substituir o conteúdo do nosso <div>
por um <template>
:
<div id="app">
<template v-for="item in 15">
<span>{{ item }}</span>
<button>Count</button>
</template>
</div>
Isso resultará em uma coleção de <span>
s e <button>
s repetidos.
Usando v-for com objetos
Podemos repetir os valores em um objeto objectItems
do modelo de dados. Isso pode ser feito adicionando a diretiva v-for
no elemento que deve ser repetido.
Vamos modificar as linhas em data()
para que retorne um objeto objectItems
:
<script>
new Vue({
el: "#app",
data() {
return {
objectItems: {
key1: 'item1',
key2: 'item2',
key3: 'item3'
}
}
}
});
</script>
Vamos substituir o conteúdo do nosso <div>
por uma lista não ordenada que repete os itens da lista:
<div id="app">
<ul>
<li v-for="item in objectItems">{{ item }}</li>
</ul>
</div>
Veja como as coisas vão ficar:
Output<div id="app">
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
</div>
Isso resultará em uma lista não ordenada com os valores de propriedade do objeto.
Além do valor da propriedade, obtemos dois parâmetros adicionais ao fazer um loop sobre objetos com Vue. Ou seja, os valores key
e index
.
O valor key
nos dá acesso à chave de propriedades atual.
O index
nos fornece o índice do item atual no loop. Esta é a posição do item na lista em loop.
Vamos substituir o conteúdo do nosso <div>
por uma lista não ordenada que repete os itens da lista com item
, key
e index
:
<div id="app">
<ul>
<li v-for="(item, key, index) in objectItems">
{{ item }} - {{ key }} - {{ index }}
</li>
</ul>
</div>
Veja como as coisas vão ficar:
Output<div id="app">
<ul>
<li>item1 - key1 - 1</li>
<li>item2 - key2 - 2</li>
<li>item3 - key3 - 3</li>
</ul>
</div>
Isso resultará em uma lista não ordenada com item
, chave
e index
.
Usando v-for com matrizes
Podemos percorrer os itens em uma matriz shoppingItems
do modelo de dados. Isso pode ser feito adicionando a diretiva v-for
no elemento que deve ser repetido.
Vamos modificar as linhas em data()
para que retorne um array shoppingItems
com objetos:
<script>
new Vue({
el: "#app",
data() {
return {
objectItems: {
key1: 'item1',
key2: 'item2',
key3: 'item3'
},
shoppingItems: [
{ name: 'apple', price: '7' },
{ name: 'orange', price: '12' }
]
}
}
});
</script>
Podemos percorrer os objetos no array shoppingItems
e acessar os valores usando uma determinada chave.
Vamos substituir o conteúdo do nosso <div>
por uma lista não ordenada que repete os itens da lista com item.name
e item.price
:
<div id="app">
<ul>
<li v-for="item in shoppingItems">
{{ item.name }} - {{ item.price }}
</li>
</ul>
</div>
Veja como as coisas vão ficar:
Output<div id="app">
<ul>
<li>apple - 7</li>
<li>orange - 12</li>
</ul>
</div>
Isso resultará em uma lista não ordenada com os valores da matriz.
Usando v-bind:key para rastrear elementos
Quando a ordem da matriz é alterada, por padrão, o Vue alteraria os dados em cada elemento existente, em vez de mover os elementos DOM para a posição atualizada.
Podemos definir o Vue para rastrear cada elemento usando uma chave. Isso faria com que ele movesse elementos em vez de substituir valores.
Esse valor deve ser exclusivo para cada elemento que está sendo iterado.
Vamos atribuir uma chave usando item.name
:
<div id="app">
<ul>
<li v-for="item in shoppingItems" v-bind:key="item.name">
{{ item.name }} - {{ item.price }}
</li>
</ul>
</div>
Agora, o Vue tem uma maneira de rastrear a identidade de um nó à medida que as alterações são feitas.
Gerenciando Mudanças
Fora da caixa, v-for
suporta métodos de mutação de matriz. Estes são push
, pop
, shift
, unshift
, splice
, sort
e reverse
. Se qualquer uma dessas operações for executada em um array, a diretiva v-for
atualiza a visualização com os novos dados.
Além disso, quando substituímos um array por um novo array, o Vue encontra a maneira mais otimizada de atualizar os itens.
Problemas com o Gerenciamento de Mudanças
As duas coisas que o Vue não pode rastrear quando alteradas em um array são:
- Definir itens diretamente.
Exemplo:
data.shoppingItems[3] = { price: 10, name: 'pineapple' };
Isso pode ser resolvido usando o método Vue.set
. Este método aceita o array
, um index
e o novo valor
.
Vue.set(data.shoppingItems, 3, { price: 10, name: 'pineapple' });
Além disso, podemos usar splice
para definir o valor em um determinado índice.
- Modificando o comprimento da matriz.
Exemplo:
data.shoppingItems.length = 2;
Podemos usar splice
para modificar o comprimento do array em vez de configurá-lo diretamente para evitar problemas.
Listas de filtragem
Podemos filtrar as listas que estão sendo exibidas sem alterar a lista original. Isso pode ser feito usando valores computed
ou tendo um método e passando valores ao definir os valores v-for
.
Usando valores computados para filtrar itens
Em vez de definir o valor diretamente na lista, apontamos para um valor computed
. Podemos escrever a lógica para filtrar dados nessa função computada.
Primeiro, vamos definir itemsLessThanTen
:
<script>
new Vue({
el: "#app",
data() {
return {
objectItems: {
key1: 'item1',
key2: 'item2',
key3: 'item3'
},
shoppingItems: [
{ name: 'apple', price: '7' },
{ name: 'orange', price: '12' }
]
}
},
computed: {
itemsLessThanTen: function() {
return this.shoppingItems.filter(function(item) {
return item.price < 10;
})
}
}
});
</script>
Então, vamos modificar o v-for
para usar itemsLessThanTen
:
<div id="app">
<ul>
<li v-for="item in itemsLessThanTen" v-bind:key="item.name">
{{ item.name }} - {{ item.price }}
</li>
</ul>
</div>
Veja como as coisas vão ficar:
Output<div id="app">
<ul>
<li>apple - 7</li>
</ul>
</div>
A função itemLessThanTen
usa a função JavaScript filter
para retornar qualquer item com um preço menor que 10.
Usando um método para filtrar itens
Nesta abordagem, passamos a mesma lista shoppingItems
diretamente para um método que definimos. Ao fazer isso, todos os itens do array seriam filtrados de acordo com a definição do método.
Primeiro, vamos definir filterItems
:
<script>
new Vue({
el: "#app",
data() {
return {
objectItems: {
key1: 'item1',
key2: 'item2',
key3: 'item3'
},
shoppingItems: [
{ name: 'apple', price: '7' },
{ name: 'orange', price: '12' }
]
}
},
computed: {
itemsLessThanTen: function() {
return this.shoppingItems.filter(function(item) {
return item.price < 10;
})
}
},
methods: {
filterItems: function(items) {
return items.filter(function(item) {
return item.price < 10;
})
}
}
});
</script>
Então, vamos modificar o v-for
para usar filterItems
:
<div id="app">
<ul>
<li v-for="item in filterItems(shoppingItems)" v-bind:key="item.name">
{{ item.name }} - {{ item.price }}
</li>
</ul>
</div>
Veja como as coisas vão ficar:
Output<div id="app">
<ul>
<li>apple - 7</li>
</ul>
</div>
O método filterItems
executa a mesma função do exemplo de valor computed
e o resultado final seria o mesmo.
Conclusão
Neste artigo, você aprendeu como usar v-for
em aplicativos Vue. Você foi apresentado a intervalos, chaves, computed
e métodos
.
Se você quiser aprender mais sobre Vue.js, confira nossa página de tópicos Vue.js para ver exercícios e projetos de programação.