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: