Manipulando Arrays e Objetos Passados por Props no Vue.js
Diferentemente de strings, números e valores booleanos, arrays e objetos são passados para os componentes por referência. Isso significa que, ao receber uma referência, o componente pode modificar diretamente os valores armazenados nela.
Modificação de Arrays
A seguir, um exemplo de como modificar arrays passados do componente pai para o filho.
<!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 :users="users"></userform>
<div>
<useritem v-for="(user, index) in users" :user="user" :index="index" :key="index" v-on:userdelete="remove"> </useritem>
</div>
</div>
<script>
const app = Vue.createApp({
data() {
return {
users: [
{ name: "Tom", age: 23 },
{ name: "Bob", age: 26 },
{ name: "Alice", age: 28 },
],
};
},
methods: {
remove(index) {
this.users.splice(index, 1);
},
},
});
app.component("userform", {
props: ["users"],
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="userAdd">Adicionar</button>
</div>`,
methods: {
userAdd() {
this.users.push({ name: this.user.name, age: this.user.age });
},
},
});
app.component("useritem", {
props: ["user", "index"],
template: `<div>
<p>Nome: {{ user.name }} <br> Idade: {{ user.age }}</p>
<button v-on:click="userDelete(index)">Remover</button>
</div>`,
methods: {
userDelete(index) {
this.$emit("userdelete", index);
},
},
});
app.mount("#app");
</script>
</body>
</html>
O componente userform
recebe uma referência ao array users
e adiciona um novo usuário ao clicar no botão. Como o array é passado por referência, a modificação feita no componente filho reflete diretamente no array do componente pai.
Já o componente useritem
adota outra abordagem. Ele recebe um elemento do array como prop
, mas não o modifica diretamente. Em vez disso, emite um evento userdelete
, passando o índice do item a ser removido. O componente pai escuta esse evento e remove o elemento correspondente.
Essa estratégia permite tanto modificar diretamente os dados do pai dentro do componente filho quanto emitir eventos para que o componente pai faça as alterações necessárias.
Modificação de Objetos
Para modificar objetos externos dentro de um componente, uma abordagem semelhante pode ser aplicada.
<!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 :user="user"></userform>
<div>
<useritem v-for="(user, index) in users" :key="index" :user="user" :index="index" v-on:userchange="change"> </useritem>
</div>
</div>
<script>
const app = Vue.createApp({
data() {
return {
users: [
{ name: "Tom", age: 23 },
{ name: "Bob", age: 26 },
{ name: "Alice", age: 28 },
],
user: {},
};
},
methods: {
change(index) {
this.user = this.users[index];
},
},
});
app.component("userform", {
props: ["user"],
template: `<div>
<input type="text" v-model="user.name" />
<input type="number" v-model="user.age" />
</div>`,
});
app.component("useritem", {
props: ["user", "index"],
template: `<div>
<p>Nome: {{ user.name }} <br> Idade: {{ user.age }}</p>
<button v-on:click="userChange(index)">Selecionar</button>
</div>`,
methods: {
userChange(index) {
this.$emit("userchange", index);
},
},
});
app.mount("#app");
</script>
</body>
</html>
O componente userform
recebe um objeto user
e o vincula diretamente aos campos de entrada. Como o objeto é passado por referência, qualquer alteração feita nos inputs reflete imediatamente no objeto original.
O componente useritem
emite o evento userchange
, passando o índice do usuário selecionado. O componente pai recebe esse evento e atualiza a referência de user
para o objeto correspondente dentro do array users
, permitindo que ele seja editado diretamente pelo formulário.
Essa abordagem mantém a reatividade e o fluxo de dados coerente dentro do Vue, garantindo que as atualizações nos objetos sejam refletidas corretamente na interface.
Documentação: