Eventos Personalizados no Vue.js
No Vue.js, a comunicação entre componentes pode ser feita por meio de props, permitindo que um componente pai envie dados para um filho. No entanto, quando é necessário enviar dados no sentido inverso, do componente filho para o pai, é preciso emitir eventos personalizados.
A estrutura básica para criar e capturar um evento personalizado é a seguinte: o componente pai escuta o evento emitido pelo filho utilizando v-on:
<child-component v-on:myevent="action"></child-component>Aqui, "myevent" é o nome do evento personalizado definido no componente filho, e "action" é o método do componente pai que será executado quando o evento for disparado.
No componente filho, o evento é emitido usando this.$emit('myevent'), onde "myevent" deve corresponder exatamente ao nome do evento que o componente pai está escutando.
Exemplo de Implementação
O exemplo a seguir demonstra um componente Vue que emite um evento para atualizar um nome de usuário:
<!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>Hello, {{ name }}</h2>
      <useredit :user="name" v-on:userchange="change"></useredit>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            name: "Tom",
          };
        },
        methods: {
          change(value) {
            this.name = value;
          },
        },
      });
      app.component("useredit", {
        props: ["user"],
        data() {
          return { userName: this.user };
        },
        template: `
                <div>
                    <input type="text" v-model="userName" v-on:input="onUserChange" />
                    <p>Name: {{ userName }}</p>
                </div>
            `,
        methods: {
          onUserChange() {
            this.$emit("userchange", this.userName);
          },
        },
      });
      app.mount("#app");
    </script>
  </body>
</html>Nesse exemplo, o evento userchange é criado no componente filho e emitido sempre que o valor do campo de entrada for alterado.
No template do componente useredit, o campo de entrada (input) está vinculado ao valor da propriedade userName por meio de v-model. Além disso, um ouvinte de evento v-on:input="onUserChange" é definido para capturar alterações no campo:
<input type="text" v-model="userName" v-on:input="onUserChange" />O método onUserChange é acionado a cada alteração no campo de entrada e emite o evento userchange, passando o valor atualizado de userName:
onUserChange() {
    this.$emit('userchange', this.userName);
}O primeiro argumento de this.$emit() define o nome do evento, enquanto os argumentos seguintes podem conter qualquer dado a ser transmitido. Neste caso, o valor atualizado do nome do usuário é enviado.
O componente useredit emite o evento userchange, que é escutado pelo componente pai. No template do componente pai, a diretiva v-on:userchange="change" captura esse evento e aciona o método change, que atualiza o valor da variável name.
<useredit :user="name" v-on:userchange="change"></useredit>change(value) {
    this.name = value;
}Como resultado, sempre que o usuário digitar um novo nome no componente useredit, o evento userchange será emitido, transmitindo o valor atualizado ao componente pai, que atualizará a variável name e refletirá a mudança na interface.

Documentação: