Como emitir eventos para comunicação entre componentes Vue
Saiba como um modelo orientado a eventos pode ajudá-lo a transmitir dados entre componentes.
Estruturar seus aplicativos da web usando uma arquitetura de componentes facilita a construção e a manutenção de seu aplicativo.
A emissão de eventos personalizados é uma maneira de lidar com a comunicação entre componentes; adereços e slots são outros dois. Os eventos personalizados permitem enviar dados do componente filho para o componente pai.
Emitir eventos de um filho para seu pai
Vue oferece muitas opções de comunicação entre componentes. Uma forma significativa de comunicação entre componentes é por meio de adereços. Props permitem que você envie dados de componentes pai para filho.
O que acontece então se você quiser enviar dados do componente filho para o componente pai? Vue permite que você emita eventos personalizados de componentes filho para pai. Este processo permite que o componente pai use dados e funções do componente filho.
Por exemplo, imagine um componente de botão com uma função que retorna um valor a cada clique. Você precisará emitir esse evento para o componente pai para permitir que o componente pai atualize seu estado ou execute uma ação com base no valor retornado.
Convenção de nomenclatura para eventos emitidos personalizados em Vue
Antes de mergulhar em como emitir eventos personalizados, você precisa entender a convenção de nomenclatura para eventos personalizados no Vue. Antes do surgimento do Vue 3, os desenvolvedores precisavam estritamente definir eventos personalizados com kebab-case, separando as palavras nos nomes com um caractere de hífen.
Agora é prática padrão definir seus eventos personalizados em kebab-case ao trabalhar com modelos HTML e camelCase ao trabalhar com JavaScript. No entanto, você pode escolher usar qualquer opção ao trabalhar com JavaScript, pois o Vue compila todos os eventos personalizados de volta para o kebab-case.
Ao emitir um evento personalizado, transmita a finalidade do evento com um nome descritivo. Isso é muito importante, principalmente quando se trabalha em equipe, para deixar claro o propósito do evento.
Como emitir eventos personalizados do componente filho para o componente pai
Existem duas maneiras de realizar a emissão de eventos personalizados no Vue. Você pode emitir eventos personalizados inline (diretamente no modelo Vue) com o método $emit que o Vue fornece. Você também pode usar a macro defineEmits disponível no Vue 3.
Emitindo eventos personalizados em Vue com o método $emit
$emit, um método Vue integrado, permite que um componente filho envie um evento para seu componente pai. Você chama esse método in-line (dentro do modelo do componente filho) para acionar o evento personalizado. O método $emit leva dois argumentos: o nome do evento que você deseja emitir e uma carga opcional que pode transportar dados adicionais.
Considere este componente filho que emite um evento para notificar o componente pai sobre um clique de botão:
<!-- ChildComponent.vue -->
<script setup>
import { ref } from 'vue';
const post = ref('')
</script>
<template>
<div>
<input type="text" v-model="post">
<button v-on:click="$emit('button-clicked', post)">Post</button>
</div>
</template>
Este bloco de código mostra como emitir um evento personalizado de um componente filho. O filho começa inicializando uma variável post com uma string vazia.
O componente filho então vincula o elemento de entrada à variável post com v-model, uma diretiva de ligação de dados Vue. Essa ligação permite que alterações feitas no campo de entrada atualizem a variável post automaticamente.
O elemento button possui uma diretiva v-on que escuta eventos de clique no botão. O clique do botão chama o método $emit com dois argumentos: o nome do evento, "botão clicado", e o valor da variável post.
O componente pai agora pode escutar o evento personalizado com a diretiva v-on para lidar com eventos no Vue:
<!-- ParentComponent.vue -->
import { ref } from "vue";
import ChildComponent from "./components/ChildComponent.vue";
const postList = ref([])
const addPosts = (post) => {
postList.value.push(post)
}
</script>
<template>
<div>
<ChildComponent @button-clicked="addPosts"/>
<ul>
<li v-for="post in postList">{{ post }}</li>
</ul>
</div>
</template>
Este bloco de código demonstra um componente pai importando e usando o componente filho anterior. O componente pai define uma variável de array postList como uma referência reativa. O componente então define uma função addPosts que é executada, recebendo um argumento post. A função adiciona uma nova postagem ao array postList com o método push().
O ouvinte de evento @button-clicked captura o evento personalizado que o ChildComponent emite quando você clica no botão. Este evento faz com que a função addPosts seja executada. Finalmente, o bloco de código anexa a diretiva v-for para renderizar listas em Vue ao elemento ul para iterar sobre o array postList.
Emitindo eventos com a macro defineEmits
O Vue 3 introduziu a macro defineEmits, que define explicitamente os eventos que um componente pode emitir. Esta macro fornece uma maneira segura de emitir eventos que levam a uma base de código mais estruturada.
Aqui está um exemplo de como você pode usar a macro defineEmits e chamá-la em seu componente filho:
<!-- ChildComponent.vue -->
<script setup>
import { ref } from "vue";
const emit = defineEmits(["button-clicked"]);
const post = ref("");
const buttonClick = () => {
emit("button-clicked", post.value);
};
</script>
<template>
<div>
<input type="text" v-model="post" />
<button v-on:click="buttonClick">Post</button>
</div>
</template>
Embora a funcionalidade permaneça a mesma, existem diferenças significativas na sintaxe do código entre o bloco de código acima e aquele com a função $emit.
Neste bloco de código, a macro defineEmits define o evento botão clicado. Ao chamar esta macro, o bloco de código retorna uma função $emit, permitindo emitir os eventos definidos. A matriz passada para a macro defineEmits dentro do componente conterá todos os eventos que você precisa emitir para o componente pai.
A seguir, o bloco de código define uma função buttonClick. Esta função emite o evento de botão clicado e a variável post para o componente pai. O bloco de modelo do componente filho abriga um elemento de botão.
O elemento button possui uma diretiva v-on:click que aciona a função buttonClick. O componente pai pode então usar o componente filho da mesma forma que fez com o método $emit.
Os desenvolvedores Vue se beneficiam de uma arquitetura baseada em componentes
Você pode se comunicar de um componente filho para seu pai emitindo eventos usando o método $emit e a macro defineEmits.
Você pode se beneficiar da arquitetura baseada em componentes do Vue, pois ela permite escrever código mais estruturado e conciso. Com estruturas JavaScript modernas como Vue, você pode usar Web Components, um padrão web W3C, para obter essa arquitetura baseada em componentes.