Vue.js: Renderização Condicional e Listas
Última atualização: 2026-10-20
A renderização condicional (v-if / v-show) e a renderização de lista (v-for) são as duas diretivas mais utilizadas nos modelos do Vue. A primeira controla se um elemento é exibido ou não, enquanto a segunda controla quantos elementos são exibidos. Juntas, elas são capazes de lidar com 90% dos cenários de interface do usuário.
Compreender as cinco principais diferenças entre v-if e v-for, bem como o uso correto de :key, é essencial para a criação de aplicativos Vue de alto desempenho.
1. O que você vai aprender
Renderização condicional
- As 5 principais diferenças entre
v-showev-if v-forIteração sobre matrizes, objetos, números e strings- O objetivo e as melhores práticas do
:key templateEnvolvendo vários elementos- Filtragem, ordenação e paginação de listas
- Otimização da rolagem virtual (mais de 10.000 itens)
2. Um pesadelo de programação: “Instruções if aninhadas” em um painel
(1) Problema: 5 tags v-if aninhadas — um pesadelo para a depuração
O código do painel da Alice ficou fora de controle:
A revisão de código feita por Charlie:
“Alice, isso está impossível de ler. São cinco níveis de aninhamento de v-if. E se adicionarmos mais duas condições? Precisamos de um padrão mais claro.”
(2) Solução com Vue: Simplificação com v-if + Propriedades calculadas
(3) Receita
- Legibilidade: 5 níveis de aninhamento → 6 linhas dispostas lado a lado
- Fácil de manter: Para adicionar uma condição, basta inserir uma linha de
v-else-if - Depuração: Cada linha tem sua própria condição, o que facilita a definição de pontos de interrupção
3. Renderização condicional com v-if / v-else-if / v-else
(1) Sintaxe básica
(2) O elemento template
(3) 5 principais casos de uso
| Cenário | Usando v-if |
|---|---|
| Conectado/Não conectado | ✅ |
| Carregando.../Carregado | ✅ |
| Sem dados/Dados disponíveis | ✅ |
| Status do erro | ✅ |
| Alternar frequentemente entre mostrar e ocultar | ❌ (Use v-show) |
▶ Exemplo: 5 maneiras de usar v-if/v-show
▶ ExperimenteSaída:
show = true → os dois <p> visíveis
show = false → v-if sai do DOM; v-show fica com display: none
type = 'B' → exibe "B"; isAdmin = true → <h1>Admin</h1> + botão
4. 5 principais diferenças entre v-show e v-if
(1) Principais diferenças
(2) 5 comparações importantes
| Aspecto | v-if | v-show |
|---|---|---|
| Manipulação do DOM | Remove o elemento quando a condição é falsa | Permanece sempre no DOM; apenas a propriedade display é alterada |
| Desempenho da troca | Ruim (destruir e reconstruir a cada vez) | Bom (apenas CSS) |
| Renderização inicial | Não renderizar se a condição for falsa | Sempre renderizar (mesmo que seja invisível) |
| Compatibilidade com transições | ✅ Perfeita (animações de entrada/saída) | ❌ Não compatível |
| Casos de uso | Troca ocasional | Troca frequente |
(3) Recomendações de seleção
// Switch Occasionally(If you are logged in/Not logged in)→ v-if
<div v-if="isLoggedIn">Welcome, {{ user.name }}</div>
<div v-else>Please login</div>
// Frequent switching (e.g. tab switch) → v-show
<button v-show="isActive">Active</button>
<button v-show="!isActive">Inactive</button>
5. Exibição de listas com v-for
(1) Iterando por um array
(2) Iteração sobre objetos
(3) Iterando por números
(4) Iteração por uma string
▶ Exemplo: 5 maneiras de usar v-for
▶ Experimente
Saída:
items = 2 → "1. iPhone", "2. MacBook"
user = { name: 'Alice' } → "name: Alice"
n in 5 → 1 2 3 4 5; em 'Hello' → H e l l o
▶ Exemplo: Prioridade entre v-if e v-for
<!-- In Vue 3, v-if has higher priority than v-for (Vue 2 is the opposite) -->
<ul>
<!-- Vue 3: First determine v-if, then v-for -->
<li v-for="user in users" v-if="user.isActive" :key="user.id">
{{ user.name }}
</li>
<!-- ✅ But Vue officially recommends using template to separate -->
<!-- ❌ Incorrect wording(Not recommended) -->
<li v-for="user in users" v-if="shouldShowUsers(user)" :key="user.id">
{{ user.name }}
</li>
<!-- ✅ Recommendations:computed Filter -->
<li v-for="user in activeUsers" :key="user.id">
{{ user.name }}
</li>
</template>
Saída:
Vue 3: v-if é avaliado antes do v-for
user não existe nesse escopo → erro ao ler user.isActive
Correção: <li v-for="user in activeUsers"> com computed
6. A finalidade de :key e as melhores práticas
(1) O que é :key?
:key Atribua um identificador exclusivo a cada item do v-for para ajudar o Vue a atualizar o DOM de forma eficiente.
(2) Por que o :key é necessário?
graph LR A[Original List A B C] --> B[New List B C D] B --> C[None key:Possible misalignment] B --> D[Has key: Update Correctly] style C fill:#ff6b6b style D fill:#42b883
Quando não há :key:
- Comparando o uso de
indexno Vue - Depois de remover A, B/C passa a ser (0)/(1), mas o Vue considera que “B/C ainda está lá”
- Provoca um desalinhamento no estado dos componentes
Quando :key estiver presente:
- Comparando IDs no Vue
- Identificar com precisão quais itens foram adicionados, excluídos ou movidos
- Desempenho ideal
(3) Melhores práticas para :key
<!-- ✅ Recommendations:The Only One ID -->
<li v-for="user in users" :key="user.id">
<!-- ✅ Second choice:Unique Field(Email、Mobile phone number, etc.)-->
<li v-for="user in users" :key="user.email">
<!-- ❌ Avoid:index(When the data changes, the alignment is off.)-->
<li v-for="(user, index) in users" :key="index">
<!-- ❌ Never, under any circumstances:random()(Every render is different,Forced Rebuild)-->
<li v-for="user in users" :key="Math.random()">
▶ Exemplo: Comparação de 5 maneiras de usar :key
▶ ExperimenteSaída:
:key="user.id" → lista estável ao reordenar
:key="i" → conteúdo desalinha após ordenar
:key="Math.random()" → lista recriada a cada render
7. Filtragem / Ordenação / Paginação de listas
(1) Filtragem + Classificação (Propriedades calculadas)
import { ref, computed } from 'vue'
const items = ref([
{ id: 1, name: 'iPhone', price: 999, category: 'phone' },
{ id: 2, name: 'MacBook', price: 2499, category: 'laptop' },
{ id: 3, name: 'iPad', price: 599, category: 'tablet' }
])
const searchQuery = ref('')
const selectedCategory = ref('all')
const sortBy = ref('price') // 'price' / 'name'
// Filter + Sort(computed Automatic Caching)
const filteredItems = computed(() => {
let result = items.value
// 1. Filter by search term
if (searchQuery.value) {
result = result.filter(item =>
item.name.toLowerCase().includes(searchQuery.value.toLowerCase())
)
}
// 2. Filter by Category
if (selectedCategory.value !== 'all') {
result = result.filter(item => item.category === selectedCategory.value)
}
// 3. Sort
result = [...result].sort((a, b) => {
if (sortBy.value === 'price') return a.price - b.price
if (sortBy.value === 'name') return a.name.localeCompare(b.name)
return 0
})
return result
})
(2) Paginação
const currentPage = ref(1)
const pageSize = ref(10)
// Data after pagination
const paginatedItems = computed(() => {
const start = (currentPage.value - 1) * pageSize.value
return filteredItems.value.slice(start, start + pageSize.value)
})
// Total Number of Pages
const totalPages = computed(() =>
Math.ceil(filteredItems.value.length / pageSize.value)
)
8. Exercício abrangente: lista com filtro, ordenação e paginação
▶ Exemplo: Exemplo completo de filtragem + ordenação + paginação de listas
▶ ExperimenteSaída:
Inicial: iPad - $599, iPhone - $999, MacBook - $2499 (por preço)
Buscar "iPho" → apenas iPhone - $999
Categoria "laptop" → apenas MacBook; 1 / 1, Next desabilitado
(1) 📊 5. 5 erros comuns
| Erro | Sintoma | Solução |
|---|---|---|
| Nenhuma :key | Desalinhamento da lista, baixo desempenho | Adicionar :key="item.id" |
| Como usar v-for e v-if juntos | Confusão sobre a prioridade do v-if | Envolvendo com template ou usando computed |
| Use “índice” como chave | Desalinhamento durante a classificação | Use um ID exclusivo |
O v-show não é compatível com <transition> |
Não é possível criar animações | Use v-if em vez disso + <transition> |
| A lista é muito grande (mais de 100.000) | A página trava | Use o vue-virtual-scroller para rolagem virtual |
❓ Perguntas Frequentes
:key é obrigatório quando se usa o v-for?:key para evitar problemas de desempenho e incompatibilidades no estado dos componentes. O ideal é usar um ID exclusivo (item.id), seguido pelo index; nunca use o random().template ou filtre usando o computed.template?template é um elemento wrapper lógico do Vue que não é renderizado no DOM. Ele é usado para evitar elementos div desnecessários quando v-if ou v-for incluem vários elementos.:key; (2) Use computed para armazenar em cache os resultados da filtragem/classificação; (3) Para listas grandes (mais de 100.000), use vue-virtual-scroller para rolagem virtual, a fim de renderizar apenas a área visível.v-for?v-for="(value, key, index) in obj", ordem dos parâmetros: valor, chave, índice.<div v-if="items.length">Column </div><div v-else> Data</div>.activeIndex a cada item: @click="activeIndex = item.id" :class="{ active: activeIndex === item.id }".📖 Resumo
- A renderização condicional com v-if (remove do DOM), enquanto v-show alterna a propriedade
display(que permanece sempre no DOM) - Use
v-ifpara trocas ocasionais ev-showpara trocas frequentes - Use
v-forpara percorrer matrizes, objetos, números e strings; use:keypara melhorar o desempenho - :key: O ideal é usar um ID exclusivo; um índice é a segunda melhor opção; não use random()
- O elemento
templateengloba vários elementos e não é renderizado no DOM - Armazenar em cache automaticamente a filtragem, a ordenação e a paginação de listas usando
computed - No Vue 3,
v-iftem precedência sobrev-for - Otimização de listas extensas com rolagem virtual (mais de 100.000 itens)
📝 Exercícios
-
Questões básicas (Dificuldade: ⭐)
Use v-if/v-else para alternar entre os estados de conectado e desconectado:
- Conectado: exibe o nome de usuário e o botão “Sair”
- Não conectado: exibe a mensagem “Faça login” e o formulário de login
- Use um template para agrupar vários elementos
-
Problemas avançados (Dificuldade: ⭐⭐)
Como criar uma lista de tarefas usando
v-for:- 3 status: Todos / Em andamento / Concluídos (alterne entre eles usando os 3 botões)
- A lista exibe as tarefas com o status correspondente
- Cada item possui os botões “Concluir” e “Excluir”
- A mensagem “Inacabado: N itens” é exibida na parte inferior
-
Problema de desafio (Dificuldade: ⭐⭐⭐)
Implementar um sistema completo de filtragem, ordenação e paginação de produtos (5 arquivos):
- Dados do produto: 30 registros, incluindo nome, preço, categoria e data de criação
- Pesquisa: Faça uma pesquisa aproximada por nome
- Filtrar por categoria: 5 categorias (todas/celular/laptop/tablet/fones de ouvido)
- Ordenar por: Preço (crescente/decrescente), Nome, Mais recentes
- Paginação: 10 itens por página, com navegação numérica entre as páginas
- Desempenho: armazena em cache os resultados calculados, filtrados e classificados
- Otimização de listas extensas: 1.000 itens de teste para garantir um desempenho sem interrupções