Como reutilizar componentes Vue com slots
Você sabe tudo sobre separação de interesses e dividiu seus componentes em partes gerenciáveis, mas como eles podem se comunicar de maneira eficaz?
Vue oferece várias maneiras pelas quais os componentes podem se comunicar entre si. Essa comunicação pode ocorrer entre dois componentes não relacionados ou entre um componente pai e um componente filho. O Vue consegue isso com recursos que incluem adereços, fornecimento/injeção e slots.
Descubra como usar slots para permitir que componentes pai e filho se comuniquem em suas aplicações Vue.
O que são caça-níqueis?
Os slots no Vue atuam como espaços reservados no modelo de um componente filho. Esses espaços reservados permitem que você passe conteúdo de componentes pai para filho de forma dinâmica.
Semelhante aos adereços que passam dados e funções dos componentes pai para os filhos, os slots permitem que você passe o conteúdo do modelo dos componentes pai para os filhos. Isso permite criar componentes mais reutilizáveis com conteúdo HTML diferente.
A sintaxe básica dos slots
Vue é conhecido por sua capacidade de aprimorar HTML com tags personalizadas que permitem construir rapidamente aplicativos web flexíveis. Os caça-níqueis não são exceção. No Vue, uma tag de slot exclusiva permite definir espaços reservados em componentes filhos para injetar conteúdo HTML.
Para definir um slot dentro de um componente filho Vue, use o elemento dentro do modelo do componente. Considere este exemplo básico:
<!-- ChildComponent.vue -->
<template>
<div>
<slot></slot>
</div>
</template>
Este exemplo mostra um componente Vue simples contendo um único slot. Você pode passar conteúdo para o slot neste componente filho a partir de um componente pai. Este conteúdo substituirá o elemento slot quando o Vue renderizar o componente filho.
Para usar o slot, passe o conteúdo do componente pai para o componente filho:
<!-- ParentComponent -->
<script setup>
import ChildComponent from './components/ChildComponent.vue';
</script>
<template>
<ChildComponent>
<h1>This is the child component</h1>
</ChildComponent>
<div>
<h3>This is the parent component</h3>
</div>
</template>
O bloco de código acima representa um componente pai que importa e usa o componente filho anterior. O componente filho recebe a mensagem "Este é o componente filho" nas tags h1 e substitui o espaço reservado por esta mensagem.
Os slots permitem definir estruturas de layout e compor componentes complexos inserindo diferentes blocos de conteúdo. Isso é especialmente benéfico quando você cria componentes de UI reutilizáveis ou constrói layouts com seções intercambiáveis.
Nomeie seus slots para usar mais de um
Ao trabalhar com componentes diferentes, talvez seja necessário definir mais de um slot em um filho. Isso pode ocorrer porque seu componente filho pode ter seções diferentes, como cabeçalho e rodapé ou título e corpo do cartão.
Vue permite definir slots com nomes para fazer referência a um slot específico ao passar conteúdo do componente pai.
Por exemplo:
<!-- ChildComponent.vue -->
<template>
<div class="card">
<div class="card-title">
<slot name="title"></slot>
</div>
<div class="card-body">
<slot name="body"></slot>
</div>
</div>
</template>
<style>
.card {
border: 1px solid #ccc;
padding: 10px;
border-radius: 4px;
}
.card-title {
font-weight: bold;
margin-bottom: 10px;
}
.card-body {
margin-bottom: 10px;
}
</style>
O bloco de código acima representa um componente filho que representa um cartão. Este componente do cartão define dois slots com dois atributos de nome: título e corpo. Você pode fazer referência a qualquer um desses slots e passar conteúdo para eles individualmente.
Para passar conteúdo para slots nomeados, use a diretiva v-slot no componente pai:
<!-- ParentComponent -->
<script setup>
import ChildComponent from "./components/ChildComponent.vue";
</script>
<template>
<div>
<ChildComponent>
<template v-slot:title>
<h2>This is the Card Title</h2>
</template>
<template v-slot:body>
<p>This is the Card Body Content.</p>
<p>It can include multiple paragraphs or any other HTML content.</p>
</template>
</ChildComponent>
</div>
</template>
Este componente pai usa o componente filho e passa conteúdo para o título e corpo do cartão. O Vue injeta o conteúdo dos blocos do modelo nos slots correspondentes do componente filho.
Tal como acontece com outras diretivas no Vue, como a diretiva v-for para renderização de lista, você precisa anexar a diretiva v-slot a uma tag HTML. Normalmente você deve anexá-lo a uma tag template.
Como outras diretivas Vue, v-slot possui uma abreviação: o símbolo #.
<template #title>
<h2>This is the Card Title</h2>
</template>
Conteúdo padrão para slots
Você pode definir slots com conteúdo padrão que será exibido quando você não transmitir nenhum do componente pai. Você pode conseguir isso simplesmente colocando conteúdo dentro do elemento slot.
Por exemplo:
<template>
<div>
<slot>
<p>Default content for the slot.</p>
</slot>
</div>
</template>
Neste exemplo, se o componente pai não fornecer nenhum conteúdo para o slot, o Vue definirá o conteúdo HTML para o conteúdo do componente filho.
Como usar slots com escopo
Os slots com escopo permitem usar dados do componente filho ao injetar conteúdo HTML do componente pai. Isso é muito útil quando você precisa renderizar dados definidos no componente filho.
Aqui está um exemplo de como você pode usar slots com escopo definido:
<!-- ChildComponent.vue -->
<script setup>
import { ref } from "vue";
const value = ref("David");
const age = ref(21);
</script>
<template>
<div>
<slot :value="value" :age="age"> </slot>
</div>
</template>
Este componente filho define duas variáveis: um valor, representando um nome, e uma idade, representando um número. O exemplo então define um slot e passa essas duas variáveis, semelhante a como você usa props ao criar componentes Vue.
Agora você pode acessar essas variáveis do componente pai anexando a diretiva v-slot à tag do componente filho:
<!-- ParentComponent -->
<script setup>
import ChildComponent from './components/ChildComponent.vue';
</script>
<template>
<div>
<ChildComponent v-slot="slotProps">
{{ slotProps.value }} is {{ slotProps.age }} years old.
</ChildComponent>
</div>
</template>
A diretiva v-slot anexada à tag ChildComponent permite que este componente pai receba dados do componente filho e os utilize no conteúdo do slot. O objeto slotProps representa os dados compartilhados.
Dentro do conteúdo do slot, {{ slotProps.value }} e {{ slotProps.age }} exibem os dados compartilhados com interpolação, uma técnica para vincular dados no Vue.
Ao trabalhar com slots nomeados, anexe a diretiva v-slot a uma tag template. Por exemplo:
<!-- ParentComponent -->
<script setup>
import ChildComponent from "./components/ChildComponent.vue";
</script>
<template>
<div>
<ChildComponent>
<template #title="titleProps">
<h2>{{ titleProps.title }}</h2>
</template>
<template #body="bodyProps">
<p>{{ bodyProps.body }}</p>
</template>
</ChildComponent>
</div>
</template>
O bloco de código acima descreve o uso de um componente filho por um componente pai. O componente pai anexa a diretiva v-slot a duas tags template, usando a abreviação para nomenclatura. As diretivas v-slot permitem que o componente pai use dados do componente filho ao renderizar conteúdo HTML.
Agora, considere o componente filho que o componente pai usa no bloco de código abaixo:
<!-- ChildComponent.vue -->
<script setup>
import { ref } from "vue";
const cardTitle = ref("This is the card title.");
const cardBody = ref("This is the card body content.");
</script>
<template>
<div class="card">
<div class="card-title">
<slot name="title" :title="cardTitle"></slot>
</div>
<div class="card-body">
<slot name="body" :body="cardBody"></slot>
</div>
</div>
</template>
Este componente filho usa slots nomeados para diferenciá-los. Vue reserva o atributo name como um identificador exclusivo para uma tag de slot. O componente filho passa os atributos title e body para o componente pai.
Slots não são o único recurso do componente Vue
Slots são um recurso poderoso do Vue que permite criar componentes reutilizáveis com conteúdo personalizável. Ao compreender a sintaxe e o uso de slots, você pode construir aplicativos Vue.js mais flexíveis e modulares.
Vue fornece outros recursos de componentes, como elementos que podem ser compostos e adereços para comunicação de componentes. Como desenvolvedor Vue, é necessário ter um conhecimento avançado desses recursos.