当前位置: 首页 > 知识库问答 >
问题:

vue3 - Vue3 + ts 子组件 emit 方法在父组件中未触发,如何解决?

卢德惠
2024-07-08

vue3.0+tsx中子组件注册的两个emit方法,点击事件btnclick在父组件中正常,然后一个接收消息的事件rollback,没触发。

子组件:

<button @click="handleEmit">点击</button>
...
const emit = defineEmits(['rollback', 'btnclick']);
...
//正常触发
const handleEmit = () => {
  emit('btnclick', '111')
};
//接收socket消息
const onMessage = (msgEvent: any) => {
    //收到服务器信息,心跳重置并发送
    startHeartbeat();
    const msg = msgEvent.data;

    if (msg.indexOf('pong') > 0) {
        return;
    }
    ElNotification.warning({
        title: '消息提醒',
        dangerouslyUseHTMLString: true,
        message: `您有一条来自${JSON.parse(msg).data.name}的新消息,请及时处理`,
        offset: 60,
    });
    emit('receivemsg', msg);
};

接收socket消息是正常的,msg也能正常打印,就是父组件无法接收事件
父组件:

<global-websocket uri="/admin/ws/info" ref="socketComponent" @rollback="rollback" @btnclick="handleBtnEmit" />
...

// 引入组件
const GlobalWebsocket = defineAsyncComponent(() => import('/@/components/Websocket/index.vue'));
const socketComponent = ref();
//子组件的emit方法 这个正常
const handleBtnEmit = (data: any) => {
    console.log(111, data);
};
//这个没打印
const rollback = (data: any) => {
    console.log(111, data);
};

父组件没触发rollback方法,有没有大神帮忙看下怎么回事

共有3个答案

郝乐心
2024-07-08

image.png
你的socket方法中emit传给父组件的名称是receivemsg,但是用的是rollback

尹兴生
2024-07-08

没问题啊,OP检查一下自定义事件的拼写问题?

Vue SFC Playground Demo

<!-- App.vue -->
<script setup>
import Comp from './Comp.vue'

const handleBtnEmit = (data) => {
    console.log("App.handleBtnEmit", data);
};

const handleRollback = (data) => {
    console.log("App.handleRollback", data);
};
</script>

<template>
  <Comp @rollback="handleRollback" @btnclick="handleBtnEmit"/>
</template>
<!-- Comp.vue -->
<script setup>
const emit = defineEmits(['rollback', 'btnclick']);

const handleBtnclick = () => {
  emit('btnclick', new Date().valueOf())
};

const handleRollback = () => {
  emit('rollback', new Date().valueOf())
}

setInterval(() => {
  handleRollback()
}, 1 * 1000)

</script>

<template>
   <button @click="handleBtnclick">点击</button>
</template>
田博易
2024-07-08

在 Vue 3 中使用 TypeScript (tsx.vue 文件中的 <script lang="ts">),子组件通过 defineEmits 定义的 emit 事件在父组件中未触发通常有以下几种可能的原因:

  1. 异步组件的加载:你正在使用 defineAsyncComponent 来异步加载子组件。如果子组件在父组件尝试监听事件之前还没有加载完成,那么父组件是无法接收到事件的。
  2. 事件名拼写错误:检查子组件中 emit 调用的事件名 'btnclick' 是否与父组件中监听的事件名完全一致(包括大小写)。
  3. 子组件内部问题:确保 handleEmit 方法确实被调用了,并且 emit 函数是可用的(没有被覆盖或改变)。
  4. Vue 开发者工具:使用 Vue 开发者工具来检查事件是否从子组件正确发出。
  5. Vue 3 的 Composition API:如果你正在使用 Composition API,确保 setup 函数中的 emit 是通过 defineEmits 正确定义的。

基于你提供的代码,以下是一些可能的解决步骤:

确保异步组件加载完成

你可以在父组件中添加一个加载完成的检查或等待机制。例如,你可以使用 onMounted 钩子来确保子组件已经加载完成。

检查事件名

确保事件名在子组件和父组件中完全一致。

检查子组件的 setup 函数

确保 setup 函数中没有覆盖或改变 emit 变量。

完整示例

如果上述检查都没问题,那么这里有一个完整的示例,包括子组件和父组件的代码,它们应该可以正常工作:

子组件 (GlobalWebsocket.vue)

<template>
  <button @click="handleEmit">点击</button>
</template>

<script lang="ts">
import { defineComponent, defineEmits } from 'vue';

export default defineComponent({
  setup() {
    const emit = defineEmits(['rollback', 'btnclick']);

    const handleEmit = () => {
      emit('btnclick', '111');
    };

    return {
      handleEmit
    };
  }
});
</script>

父组件

<template>
  <global-websocket uri="/admin/ws/info" @rollback="rollback" @btnclick="handleBtnEmit" />
</template>

<script lang="ts">
import { defineComponent, ref, defineAsyncComponent } from 'vue';
import GlobalWebsocket from '/@/components/Websocket/index.vue'; // 确保路径正确

const GlobalWebsocketAsync = defineAsyncComponent(() => import('/@/components/Websocket/index.vue'));

export default defineComponent({
  components: {
    GlobalWebsocket: GlobalWebsocketAsync // 使用异步组件
  },
  setup() {
    const handleBtnEmit = (data: any) => {
      console.log(111, data);
    };

    return {
      handleBtnEmit
    };
  },
  methods: {
    rollback() {
      // 处理 rollback 事件
    }
  }
});
</script>

请注意,我在父组件中直接使用了 GlobalWebsocketAsync 作为组件名,而不是通过 ref。如果你需要使用 ref 来访问子组件的实例,确保你只在需要的时候(例如在某个方法中)使用它,而不是在模板中。在模板中直接使用 ref 的值作为组件是不正确的。

 类似资料:
  • vue3中子组件向父组件传值 在传值的时候为什么只能在声明一个方法的时候传递,而不能在定义click的时候传递呢

  • 如何在Children内部拿到父级的ref? 父级是不同的组件

  • 本文向大家介绍解决Vue.js父组件$on无法监听子组件$emit触发事件的问题,包括了解决Vue.js父组件$on无法监听子组件$emit触发事件的问题的使用技巧和注意事项,需要的朋友参考一下 最近学习vuejs看例子中用$on无法监听子组件$emit触发事件: 使用版本 vue.js 2.2.5 参考文献 1.vuejs API 2.解决实例 问题分析 1.之前写的自定义组件事件触发为this

  • 主要内容:全局组件实例,实例,实例,全局组件实例,局部组件实例,Prop,Prop 实例,Prop 实例组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树: 每个 Vue 应用都是通过用 createApp 函数创建的,传递给 createApp 的选项用于配置根组件。当我们挂载应用时,该组件被用作渲染的起点。 一个应用需要被挂载到一

  • 问一个vue3 setup语法糖中使用onBeforeEnter的问题 这段代码是网上搜索的。但是在项目中没有进入beforeRouteEnter,不知道是什么问题。项目中这个路由是有keep-alive缓存的。或者大家有没有更好的方法,在vue3中监听到其他路由跳转到本组件 解决问题

  • 父组件 子组件 为什么执行getSonData的时候,无法获取到子组件的data?sonRef.value.data只能在onMounted内使用吗?不能在父组件的方法里执行?

  • 问题:为啥子组件重置把 formData.value 置空后,父组件的 form 不同步生效?