No desenvolvimento de aplicações com Vue.js, a arquitetura baseada em componentes exige estratégias eficientes para o compartilhamento de informações. A gestão de estado e a transferência de dados entre diferentes níveis da árvore de componentes são fundamentais para criar interfaces dinâmicas e reativas. Abaixo, exploramos as três abordagens mais comuns para a comunicação entre componentes no Vue 2.0.
1. Fluxo de Dados Descendente: De Pai para Filho (Props)
O método primário de enviar dados para componentes internos é através de props. Este mecanismo segue o princípio do fluxo de dados unidirecional, onde o componente pai "seringa" informações no componente filho.
Componente Principal (Pai):
<template>
<div class="container-pai">
<h2>Área do Pai</h2>
<input type="text" v-model="usuarioLogado" placeholder="Digite o nome do usuário">
<!-- Passando a propriedade para o componente filho -->
<ExibicaoPerfil :nomeUsuario="usuarioLogado" />
</div>
</template>
<script>
import ExibicaoPerfil from './ExibicaoPerfil.vue'
export default {
components: { ExibicaoPerfil },
data() {
return {
usuarioLogado: ''
}
}
}
</script>
Componente Interno (Filho):
<template>
<div class="perfil-card">
<p>Perfil Ativo: {{ nomeUsuario }}</p>
</div>
</template>
<script>
export default {
props: {
nomeUsuario: {
type: String,
default: 'Visitante'
}
}
}
</script>
2. Comunicação Ascendente: De Filho para Pai (Eventos)
Para que um componente filho notifique o pai sobre mudanças ou ações do usuário, utilizamos a emissão de eventos customizados através do método $emit.
Componente Filho (Emissor):
<template>
<div class="secao-filho">
<button @click="notificarMudanca">Atualizar Status</button>
</div>
</template>
<script>
export default {
data() {
return {
novoStatus: 'Processado com Sucesso'
}
},
methods: {
notificarMudanca() {
// Emite um evento chamado 'statusAlterado' carregando um payload
this.$emit('statusAlterado', this.novoStatus);
}
}
}
</script>
Componente Pai (Receptor):
<template>
<div>
<p>Notificação do Sistema: {{ logMensagem }}</p>
<!-- Escutando o evento emitido pelo filho -->
<StatusCard @statusAlterado="atualizarInterface" />
</div>
</template>
<script>
import StatusCard from './StatusCard.vue'
export default {
components: { StatusCard },
data() {
return {
logMensagem: 'Aguardando ação...'
}
},
methods: {
atualizarInterface(valor) {
this.logMensagem = valor;
}
}
}
</script>
3. Comunicação entre Componentes sem Relação Direta (Event Bus)
Quando componentes que não possuem uma relação direta de parentesco precisam trocar informações, e a implementação do Vuex parece excessiva, utilizamos um Event Bus. Trata-se de uma instância isolada do Vue que atua como um hub central de eventos.
Configuração do Barramento (event-bus.js):
import Vue from 'vue';
export const EventBus = new Vue();
Componente Emissor (Componente A):
<template>
<button @click="dispararAlerta">Enviar Alerta Global</button>
</template>
<script>
import { EventBus } from './event-bus.js';
export default {
methods: {
dispararAlerta() {
EventBus.$emit('alertaGlobal', 'Nova atualização disponível!');
}
}
}
</script>
Componente Receptor (Componente B):
<template>
<div class="notificacao-box">
Mensagem: {{ alerta }}
</div>
</template>
<script>
import { EventBus } from './event-bus.js';
export default {
data() {
return {
alerta: ''
}
},
created() {
// Registra o listener quando o componente é criado
EventBus.$on('alertaGlobal', (msg) => {
this.alerta = msg;
});
},
beforeDestroy() {
// É importante remover o listener para evitar memory leaks
EventBus.$off('alertaGlobal');
}
}
</script>