Vue.js: Slots

Última atualização: 2026-10-20

Os slots fazem parte da API de Distribuição de Conteúdo do Vue — os componentes pais podem inserir qualquer conteúdo nos “slots” de um componente filho. Os slots tornam os componentes tão flexíveis quanto os “modelos”: os componentes pais controlam o que é exibido, enquanto os componentes filhos controlam onde isso é exibido.

O Vue 3 oferece três tipos de slots: slots padrão, slots nomeados e slots com escopo. Esta lição vai ajudá-lo a dominar o uso e as melhores práticas para esses três tipos.

Template e Auxiliares relacionados:useSlots()

1. O que você vai aprender


2. O desafio de não poder personalizar o conteúdo de um componente de cartão

(1) Desafio: 5 estilos de cartão, exigindo a criação de 5 componentes

O administrador do site de comércio eletrônico da Alice precisava de 5 tipos de cartões:

VUE
<!-- ❌ The "Broken" Version:5 component -->
<!-- ProductCard.vue -->
<div class="card">{{ product.name }}</div>

<!-- UserCard.vue -->
<div class="card">{{ user.name }}</div>

<!-- OrderCard.vue -->
<div class="card">Order #{{ order.id }}</div>

<!-- 5 component,90% The code is the same,The only difference is the content -->

O gerente de produto Charlie:

“Alice, preciso de mais 5 tipos de cartão na próxima semana. Não podemos ficar adicionando novos componentes. Precisamos de um cartão flexível que aceite qualquer tipo de conteúdo.”

(2) Solução com slots do Vue: 1 BaseCard, com conteúdo fornecido pelo componente pai

1 BaseCard.vue → uma variedade infinita de cartões. Sempre que você adicionar um novo, basta escrever o conteúdo — não é preciso modificar o componente.

(3) Receita

Após usar os slots:


3. Slot padrão

(1) Uso básico

Resultados da renderização:

HTML
<div class="card">
  <h3>Hello</h3>
  <p>This is the card content</p>
</div>

(2) Conteúdo padrão (alternativo)

VUE
<!-- The parent component does not pass content -->
<BaseCard />

<!-- Rendering:<p>No content provided</p> -->

<!-- Passing Content from the Parent Component -->
<BaseCard>
  <p>Custom content</p>
</BaseCard>

<!-- Rendering:<p>Custom content</p>(Override Default)-->

(3) 5 principais casos de uso

Cenário Uso
Conteúdo do cartão <slot />
Texto do botão <slot />
Item da lista <slot :item="item" />
Campo do formulário <slot />
Corpo da caixa modal <slot />

▶ Exemplo: BaseCard.vue (padrão + slots nomeados)

▶ Experimente

Saída:

TEXT
<BaseCard> sem conteúdo → "No content" no corpo
Com #header → cabeçalho "Product Name"
Com #footer → rodapé com "View Details"

4. Slots nomeados

(1) Definição de slots nomeados

(2) Como usar componentes pai (3 sintaxes)

(3) Nomes dinâmicos de slots

(4) Verifique se há um encaixe


5. Espaços para miras telescópicas

(1) Ponto-chave: os componentes filhos passam dados para os slots do componente pai

Resultados da renderização:

HTML
<ul>
  <li><p>1. Alice (alice@example.com)</p></li>
  <li><p>2. Bob (bob@example.com)</p></li>
  <li><p>3. Charlie (charlie@example.com)</p></li>
</ul>

(2) 5 Padrões de encaixe para miras telescópicas

Padrão Implementação do componente pai Finalidade
Aceita todos os props <template #default="slotProps"> Aceita o objeto inteiro
Desconstrução <template #default="{ user }"> Use apenas os campos de que você precisa
Renomear <template #default="{ user: u }"> Evitar conflitos de variáveis
Valor padrão <template #default="{ user = defaultUser }"> Forneça um valor padrão durante a desconstrução
Sem modelo {{ slotProps.user.name }} Cenário simples (espaço padrão)

(3) Exemplo completo: Lista personalizável

▶ Experimente

▶ Exemplo: Exemplo completo de slots de escopo

▶ Experimente

Saída:

TEXT
Tabela com as colunas de columns e uma linha por item de data
#cell-status → <span class="badge active">active</span>
#cell-actions → botão Edit em cada linha

6. $slots e useSlots

(1) $slots Acesso aos slots

(2) useSlots (API de Composição)

VUE
<script setup>
import { useSlots } from 'vue'

const slots = useSlots()

// Check if the slot exists
if (slots.header) {
  console.log('Header slot exists')
}

// Dynamic Rendering
if (slots.default) {
  console.log('Default slot exists')
}
</script>

(3) $slots x useSlots

Dimensão $slots useSlots()
Tipo de API Usada diretamente nos modelos Usada em JS (API de Composição)
Voltar Objeto Slot Objeto Slot (formato refs)
Cena Dentro do modelo Dentro de <script setup>

▶ Exemplo: 5 Principais usos de $slots

▶ Experimente

Saída:

TEXT
slots.header existe → "Has header"
Object.keys(slots) → cada nome renderizado via <slot :name="name" />
Sem slot default → "Default fallback"

7. Exercício abrangente: 5 maneiras de usar o BaseCard

▶ Exemplo: 5 maneiras de usar o BaseCard

▶ Experimente

Saída:

TEXT
1. Só corpo → "Simple content"
3. header + body + footer → "Order #12345", "Total: $99.99", botão
5. Slot de escopo → Edit/Delete recebem { user }

(1) 📊 4. Referência rápida para 5 erros comuns

Erro Sintoma Solução
Nome do slot com erro ortográfico Conteúdo não exibido Verifique se <slot name="..."> e #name correspondem
Vários elementos raiz no componente pai Aviso O componente pai está envolto em <template #name>
v-slot (sintaxe antiga) Compatível com o Vue 2 Use v-slot:header ou #header em vez disso
Slot padrão não passado Componente pai não exibido Verifique o conteúdo <Component /> no componente pai
Os slots de escopo não são desestruturados Os modelos são prolixos Desestruturação com { user, index }

(2) 📊 5. 5 Comparações de desempenho

Sintaxe Compilação Desempenho Recomendações
<slot /> Estático ⭐⭐⭐⭐⭐ Padrão
<slot name="x" /> Estático ⭐⭐⭐⭐⭐ Nomeado
<slot :x="x" /> Estático ⭐⭐⭐⭐ Alcance
v-if="$slots.x" Condição ⭐⭐⭐⭐ Detectado
useSlots() Tempo de execução ⭐⭐⭐ Usado em JS

Template e Auxiliares relacionados:useSlots()

❓ Perguntas Frequentes

P Qual é a diferença entre slots e props?
R Os props passam dados (qualquer valor em JavaScript), enquanto os slots passam conteúdo (fragmentos de HTML/componentes). Os props são adequados para opções de configuração, enquanto os slots são adequados para personalização de conteúdo.
P Quando os slots de escopo devem ser usados?
R Quando um componente pai precisa personalizar sua renderização com base nos dados de um componente filho. Por exemplo: renderizar colunas de tabela, renderizar itens de lista ou organizar o layout do conteúdo de cartões.
P Qual é a diferença entre v-slot e a forma abreviada #?
R São totalmente equivalentes; #header is a shorthand for v-slot:header. Recomendamos usar a forma abreviada (é mais concisa).
P É possível nomear o slot padrão?
R Não é necessário nomear o slot padrão; <slot /> é o valor padrão. Se for absolutamente necessário nomeá-lo, use <slot name="default" />; o componente pai pode usar <template #default> ou simplesmente passar o conteúdo diretamente.
P É possível passar slots como props?
R Não é possível passar um slot diretamente como prop. No entanto, é possível passar um VNode ou uma função de renderização como prop (uso avançado). Na maioria dos casos, basta usar <slot>.
P Como faço para detectar o slot de um componente filho em um componente pai?
R Use $slots (modelo) ou useSlots() (JS). O componente filho expõe o slot usando <slot>, e o componente pai o preenche usando <template #name>.
P Os slots nomeados podem ter conteúdo padrão?
R Sim. <slot name="header"><h3>Default Header</h3></slot>. Esse conteúdo é exibido quando o componente pai não passa um cabeçalho.

📖 Resumo


📝 Exercícios

  1. Questões básicas (Dificuldade: ⭐)

    Implemente um componente Button simples:

    • BaseButton.vue: Slot padrão + 3 variantes (principal/sucesso/perigo)
    • props: variant (String)
    • Componente pai: Testar 3 variantes + conteúdo personalizado do slot
  2. Problemas avançados (Dificuldade: ⭐⭐)

    Implemente o componente BaseLayout:

    • Componentes filhos: 3 slots nomeados (cabeçalho / padrão / rodapé)
    • Componente pai: use o BaseLayout para implementar a página do painel
    • Use $slots para verificar se o slot existe
    • Adicionar conteúdo padrão (alternativo)
  3. Problema de desafio (Dificuldade: ⭐⭐⭐)

    Implementar um sistema completo de componentes DataTable:

    1. DataTable.vue: Recebe colunas + dados e renderiza a tabela
    2. Espaço de escopo: #cell-{key} Permite que os componentes pai personalizem as células
    3. Slot padrão: exibe o valor original quando o componente pai não fornece um
    4. Exemplo de componente pai: Tabela de usuários + Tabela de pedidos — Dois métodos diferentes de exibição de colunas
    5. Desempenho: o v-memo armazena as linhas em cache (evita a redesenho quando os dados permanecem inalterados)
    6. Tipagem forte do TypeScript
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%