Comunicação entre Componentes Irmãos no Vue.js
Essa comunicação não ocorre diretamente, mas sim por meio do componente pai. No exemplo a seguir, dois componentes filhos interagem entre si por meio do componente pai.
<!DOCTYPE html>
<html>
<head>
<title>Componentes Vue.js</title>
<meta charset="utf-8" />
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<h2>User</h2>
<useredit :name="user" @userchange="change"></useredit>
<userinfo :name="user" @userreset="reset"></userinfo>
</div>
<script>
const app = Vue.createApp({
data() {
return {
user: "Tom",
};
},
methods: {
change(name) {
this.user = name;
},
reset() {
this.user = "Tom";
},
},
});
app.component("useredit", {
props: ["name"],
template: `<div>
<input v-model="username" />
<button @click="save">Save</button>
</div>`,
data() {
return { username: this.name };
},
watch: {
name(newVal) {
this.username = newVal;
},
},
methods: {
save() {
this.$emit("userchange", this.username);
},
},
});
app.component("userinfo", {
props: ["name"],
template: `<div>
<p>Nome: {{ name }}</p>
<button @click="reset">Reset</button>
</div>`,
methods: {
reset() {
this.$emit("userreset");
},
},
});
app.mount("#app");
</script>
</body>
</html>
O ponto-chave desse exemplo é que os dados manipulados pelos dois componentes filhos são armazenados no estado global do componente pai. Ambos os componentes, useredit
e userinfo
, recebem o nome do usuário diretamente do componente pai, garantindo que compartilhem os mesmos dados sem se comunicar diretamente entre si.
O primeiro componente filho, useredit
, recebe o nome do usuário como prop :
props: ["name"],
Porém, props
são somente leitura dentro do componente. Como useredit precisa modificar esse nome e enviar o valor atualizado para outro componente, ele define uma propriedade interna username
:
data() {
return { username: this.name }
},
Essa propriedade é vinculada ao campo de entrada no template:
<input v-model="username" /><button @click="save">Save</button>
Ao clicar no botão de salvar, o método save
é chamado e emite o evento userchange
:
methods: {
save() {
this.$emit("userchange", this.username);
}
}
O componente pai escuta esse evento e atualiza a variável user
:
methods: {
change(name) {
this.user = name;
}
}
Isso garante que qualquer alteração feita em useredit
seja refletida automaticamente em userinfo
.
Para garantir que useredit
também atualize username
caso o nome do usuário seja alterado por outro componente, um watcher é definido:
watch: {
name(newVal) {
this.username = newVal;
}
}
Sempre que name mudar externamente, username será atualizado.
O segundo componente filho, userinfo
, também recebe name
como prop:
props: ["name"];
Diferente de useredit
, ele não altera diretamente esse valor. Em vez disso, ao pressionar o botão de reset, emite o evento userreset
:
methods: {
reset() {
this.$emit("userreset");
}
}
O componente pai escuta esse evento e redefine o nome do usuário para o valor original:
methods: {
reset() {
this.user = 'Tom';
}
}
Neste exemplo, o componente pai atua como mediador da comunicação entre useredit
e userinfo
. Os componentes irmãos não interagem diretamente, mas se comunicam de forma indireta por meio da atualização do estado do pai.
Essa abordagem mantém os componentes filhos desacoplados, tornando o código mais modular e fácil de manter.
Documentação: