vue 3 emite la advertencia “Oyentes de eventos extraños que no emiten”

3 minutos de lectura

Estoy tratando de emitir datos de niño a padre usando la API de composición

Recibo la siguiente advertencia.

[Vue warn]: Los detectores de eventos extraños que no emiten (recuento actualizado) se pasaron al componente, pero no se pudieron heredar automáticamente porque el componente representa fragmentos o nodos raíz de texto. Si se pretende que el oyente sea solo un oyente de eventos personalizado del componente, declárelo usando la opción “emits”. en en

childcomponent.vue


<template>
  <h1>{{ store.count }}</h1>
  <button @click="fired">click me</button>
</template>

<script>
import useStore from "../store/store.js";
export default {
  name: "HelloWorld",
  setup(_,{ emit }) {
    const store = useStore();

    const fired = () => {
      store.count++;
      emit("updatedcount", store.count);
    };

    return {
      store,
      fired
    };
  },
};
</script>


parentcomponent.vue


<template>
  <div>
    {{ hello }}
    <br />
    <br />
    <input type="text" v-model="hello.searchQuery" />
    <br><br>
    <button @click="hello.count--">click me too!</button>
    <hello-world @updatedcount="mydata" />
  </div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";
import useStore from "./store/store.js";

export default {
  components: {
    HelloWorld,
  },
  setup() {
    const hello = useStore();

    function mydata(event) {
      console.log(event);
    }

    return {
      hello,
      mydata
    };
  },
};
</script>

  • La respuesta aceptada funciona muy bien, pero también puede envolver su componente secundario en un solo div también.

    – Porque

    16 oct a las 15:45

Avatar de usuario de Thomas
Tomás

Creo que necesitas definir el emits en tu componente: https://v3.vuejs.org/guide/component-custom-events.html#defining-custom-events

export default {
  name: "HelloWorld",
  emits: ["updatedcount"], // <--- add this line
  setup(_,{ emit }) {
    ...
  },
};

  • @ Fanna1119 También me tomó un tiempo volver a encontrarlo, así que no te culpes 😉

    – Tomás

    6 de octubre de 2020 a las 8:56

  • Tenga en cuenta que probablemente sea mejor por ahora nombrar el evento de la forma en que lo hizo: sin guiones, solo letras minúsculas. Si lo nombra kebab-case, el tiempo de ejecución se queja de que no lo declaró como emit en camelCase; por otro lado, si lo nombra camelCase, EsLint se queja porque se supone que los eventos son kebab-case.

    – Tobías Feil

    20 de noviembre de 2020 a las 11:47

  • Gracias, Creador del Universo, por crear SoF, para que buenas personas puedan publicar tan buenas respuestas.

    – Michael Zelensky

    3 de agosto de 2021 a las 14:13

  • esto funciona para mi. Gracias

    – SefaUn

    13 ene a las 21:31


  • @MichaelZelensky Creo que quieres decir gracias Jeff Atwood y Joel Spolsky 😏

    – hitautodestruct

    20 de enero a las 8:17

actualizar:

en la configuración del script vue 3 que harías

const emits = defineEmits(["updatedcount"])

emits("updatedcount", store.count);

Al ver este error en mis propias aplicaciones vue 3, descubrí que envolver el contenido de la plantilla de un componente en un div vacío soluciona el problema que creo que se relaciona con la parte del mensaje de error “no se pudo heredar automáticamente”.

Parece que la forma en que funciona vue es que vue intentará usar la herencia de atributos para eventos comunes como @click y @input para pasar a elementos subyacentes, pero cuando hay varios elementos hermanos en la raíz de un componente, no sabe cuál. elegir.

Tenga en cuenta que estos eventos podrían cambiar algunos comportamientos, ya que el nuevo div principal envolvente ahora tendrá eventos vinculados directamente a él.

<template>
  <div>
    <h1>{{ store.count }}</h1>
    <button @click="fired">click me</button>
  </div>
</template>

En vue3, debe definir las emisiones, su componente secundario se vería así:

childcomponent.vue:

    <template>
      <h1>{{ store.count }}</h1>
      <button @click="fired">click me</button>
    </template>
    
    <script>
    import useStore from "../store/store.js";
    export default {
      name: "HelloWorld",
      emits :{
          updatedcount: null,
        },
      data: () => ({
            store: useStore(),
      }),
      methods:
        fire () {
          store.count++;
          this.$emit("updatedcount", store.count);
        },
      
    };
    </script>

¿Ha sido útil esta solución?