Conheça o Rocketseat Para Empresas
Oferecemos soluções personalizadas para empresas de todos os portes.
Fala, dev! 👋 Já se pegou copiando e colando o mesmo bloco de HTML e CSS em cinco arquivos diferentes, só mudando uma corzinha ou um texto? Se a resposta for sim, você está criando o que chamamos de "débito técnico" sem nem perceber.
Neste artigo, vamos resolver isso de uma vez por todas. Você vai aprender a criar componentes reutilizáveis no Vue.js utilizando a Composition API e
<script setup>. Vamos sair do básico e construir um componente inteligente que se adapta a diferentes contextos.Bora codar? 🚀
O que é um componente reutilizável?
Antes de abrir o VS Code, precisamos alinhar o conceito. Um componente reutilizável no Vue.js é um pedaço de interface que funciona de forma isolada, aceita configurações externas (Props) e pode receber conteúdo dinâmico (Slots).
💡 A Analogia do LEGO: Imagine que você está construindo um castelo de LEGO. Você não fabrica um tijolo novo cada vez que precisa levantar uma parede. Você pega um tijolo padrão (o componente) e decide se ele será vermelho, azul ou amarelo (as props).
A ideia é escrever o código uma vez e usar em qualquer lugar. Isso garante:
- Manutenibilidade: Mudou o design? Muda em um lugar só.
- Produtividade: Foco na lógica, não em reescrever HTML.
- Padronização: Todo o app segue o mesmo estilo visual.
O cenário do mundo real: o botão universal
Vamos fugir do "Hello World". Vamos criar um componente que todo sistema precisa: um Botão (
BaseButton).Imagine que no seu e-commerce você tem botões de "Comprar" (verde), "Cancelar" (vermelho) e "Ver Detalhes" (azul). Se você fizer três botões separados, seu código vira uma bagunça. Vamos unificar isso.
1. A estrutura básica (o erro comum)
Um iniciante faria assim no arquivo
App.vue:<button class="btn-primary">Comprar</button> <button class="btn-danger">Excluir</button>
Se o designer pedir para mudar a borda de todos os botões, você terá que editar linha por linha. Vamos criar nosso componente para resolver isso.
Mão na massa: criando o BaseButton.vue
Crie um arquivo chamado
BaseButton.vue dentro da pasta components. Vamos usar a sintaxe moderna do Vue 3 (<script setup>).Passo 1: recebendo dados com Props
As Props são como os parâmetros de uma função. Elas permitem que o componente pai "converse" com o filho, passando dados.
<script setup> // Definindo as propriedades que nosso botão aceita defineProps({ label: { type: String, required: true // Obrigamos a passar um texto }, variant: { type: String, default: 'primary', // Se não passar nada, será 'primary' validator: (value) => ['primary', 'danger', 'outline'].includes(value) } }) </script> <template> <button class="btn" :class="`btn-${variant}`"> {{ label }} </button> </template> <style scoped> .btn { padding: 10px 20px; border-radius: 8px; border: none; cursor: pointer; font-weight: bold; transition: opacity 0.2s; } .btn:hover { opacity: 0.9; } /* Variantes de estilo */ .btn-primary { background-color: #8257e5; color: white; } .btn-danger { background-color: #e83f5b; color: white; } .btn-outline { background-color: transparent; border: 2px solid #8257e5; color: #8257e5; } </style>
⚠️ Atenção: Note o uso do validator. Isso é uma boa prática essencial! Ele garante que ninguém tente passar uma cor que não existe, como btn-abobora. O Vue vai avisar no console se isso acontecer.
Passo 2: Flexibilidade com Slots
E se quisermos adicionar um ícone dentro do botão? Passar HTML via
props é má prática e difícil de ler. Para isso, usamos Slots.O Slot é como um "buraco" no seu componente onde você pode encaixar qualquer coisa.
Vamos atualizar o
BaseButton.vue:<template> <button class="btn" :class="`btn-${variant}`"> <slot> {{ label }} </slot> </button> </template>
Agora o uso fica muito mais poderoso. Veja só como usaríamos no componente pai (
App.vue):<script setup> import BaseButton from './components/BaseButton.vue'; </script> <template> <div class="container"> <BaseButton label="Salvar Alterações" /> <BaseButton variant="danger"> 🗑️ Excluir Produto </BaseButton> <BaseButton variant="outline" label="Voltar" /> </div> </template>
Passo 3: emitindo eventos
Um botão serve para ser clicado, certo? No Vue, os eventos nativos (como
@click) são passados automaticamente para o elemento raiz do componente. Mas, é uma boa prática declarar o que seu componente emite para facilitar a leitura.No
BaseButton.vue:<script setup> // ... props anteriores // Declaramos que este componente emite um evento de clique const emit = defineEmits(['action']) function handleClick() { console.log('Botão clicado no componente filho!'); emit('action'); // Avisa o pai que a ação ocorreu } </script> <template> <button class="btn" :class="`btn-${variant}`" @click="handleClick" > <slot>{{ label }}</slot> </button> </template>
Recapitulando: o checklist do componente perfeito
Para garantir que seu componente é realmente profissional, verifique sempre estes 3 pontos:
- É genérico? Ele não deve conter lógica de negócio (ex: não chame de
BotaoComprar, chame deBaseButton).
- Tem validação? Use
requiredevalidatornas props para evitar erros bobos.
- É flexível? Use Slots para conteúdo e classes dinâmicas para estilo.
Conclusão e próximo passo
Viu como é simples? Transformamos um monte de código repetido em um arquivo limpo, organizado e fácil de manter. Agora, se o design do botão mudar, você altera apenas o
BaseButton.vue e a mágica acontece em toda a aplicação. ✨Desafio para você:
Tente criar um componente de Card (
BaseCard) que receba um título via prop e tenha um slot para o conteúdo principal.Se curtiu esse conteúdo e quer dominar mais sobre o ecossistema Vue, continua acompanhando!
Bora codar e até a próxima! 💜
Conheça o Rocketseat Para Empresas
Oferecemos soluções personalizadas para empresas de todos os portes.
NewsletterReceba conteúdos inéditos e novidades gratuitamente
