Passando Funções de Callback para Componentes no Vue.js
Funções de callback permitem a comunicação entre componentes pai e filho no Vue.js. Elas são passadas como props
e podem ser chamadas pelo componente filho.
Considere o seguinte exemplo:
<!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">
<h3>Value {{ count }}</h3>
<counter :changefn="increase"></counter>
</div>
<script>
const app = Vue.createApp({
data() {
return { count: 0 };
},
methods: {
increase() {
this.count++;
},
},
});
app.component("counter", {
props: ["changefn"],
template: `<div><button v-on:click="changefn()">+</button></div>`,
});
app.mount("#app");
</script>
</body>
</html>
Neste exemplo, o objeto Vue define um contador armazenado na variável count
e um método increase()
para incrementá-lo. Esse método não é chamado diretamente no componente pai, mas sim no componente filho counter
.
A referência ao método increase
é passada para o componente counter
por meio da prop
chamada changefn
:
<counter :changefn="increase"></counter>
Dentro do componente counter
, esse método é chamado ao clicar no botão:
<button v-on:click="changefn()">+</button>
Sempre que o botão for pressionado, o método do componente pai será acionado, aumentando o valor da variável count
exibida na tela.
Passando Paramentros para Funções de Callback
Agora, veja um exemplo onde há uma lista de usuários, com a possibilidade de adicionar e remover itens:
<!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>Lista de Usuários</h2>
<userform :addfn="add"></userform>
<div>
<useritem v-for="(user, index) in users" :user="user" :key="index" :index="index" :removefn="remove"> </useritem>
</div>
</div>
<script>
const app = Vue.createApp({
data() {
return {
users: [
{ name: "Tom", age: 23 },
{ name: "Bob", age: 26 },
],
};
},
methods: {
remove(index) {
this.users.splice(index, 1);
},
add(user) {
this.users.push(user);
},
},
});
app.component("userform", {
props: ["addfn"],
data() {
return {
user: { name: "", age: 18 },
};
},
template: `<div>
<input type="text" v-model="user.name" />
<input type="number" v-model="user.age" />
<button v-on:click="addfn({name: user.name, age: user.age})">Adicionar</button>
</div>`,
});
app.component("useritem", {
props: ["user", "index", "removefn"],
template: `<div>
<p>Nome: {{ user.name }} <br> Idade: {{ user.age }}</p>
<button v-on:click="removefn(index)">Remover</button>
</div>`,
});
app.mount("#app");
</script>
</body>
</html>
O objeto Vue exibe uma lista de usuários na tela e define dois métodos: add
para adicionar um novo usuário e remove
para remover um item da lista.
O componente userform
representa um formulário de entrada. O método add
é passado como prop
chamada addfn
:
<userform :addfn="add"></userform>
Dentro do userform
, a função addfn
recebe os valores inseridos e aciona o método add
do componente pai.
O componente useritem
representa um item da lista. Ele recebe o método remove
como prop chamada removefn
. Ao clicar no botão de remoção, essa função é chamada, acionando o método remove
do componente pai.
Esse padrão permite que os componentes filhos apenas chamem as funções definidas no componente pai, sem modificar diretamente os dados. Dessa forma, a lógica de manipulação da lista fica centralizada no componente pai, enquanto os filhos apenas disparam os eventos necessários.
Documentação: