Vue单文件组件间通过Emit触发函数执行失败问题
Vue3 子组件 emit 未触发父组件方法的问题解决
问题分析与修复步骤
1. 事件监听绑定位置错误
你把触发切换的事件监听@toggle-subheader绑定到了TopicBar组件上,但实际发出emit的是Header组件,需将监听移到Header标签上:
<header> <Header @toggle-subheader="subslide"/> </header>
2. jQuery 方法名大小写错误
jQuery 的滑动方法是小写开头的slideUp()和slideDown(),你写的大写SlideUp()会导致方法不存在,修改subslide函数:
function subslide(){ subheaderstate.value = !subheaderstate.value; if(subheaderstate.value){ $('#topicbar').slideUp(); // 改为小写 } else{ $('#topicbar').slideDown(); // 改为小写 } }
3. Header 组件 emit 写法错误(Setup 与 Options API 混合冲突)
你在 Header 组件中混合使用了<script setup>和 Options API,这种情况下 Options API 里的this.$emit无法被 setup 语法正确识别,需统一用<script setup>的方式定义 emit:
替换 Header.vue 的脚本部分,删除 Options API 的<script>标签,改用defineEmits:
<script setup lang="ts"> import $ from 'jquery'; // 定义要触发的事件 const emit = defineEmits(['toggleSubheader']); function flip(){ const $arrow = $("#header_arrow"); const isFlipped = $arrow.hasClass("flipp"); if(isFlipped) { $arrow.removeClass("flipp"); $arrow.css({"transform":"rotate(0deg)", "transition-duration":"1s"}); } else{ $arrow.addClass("flipp"); $arrow.css({"transform":"rotate(180deg)", "transition-duration":"1s"}); } } // 触发 emit 事件 function sub(){ emit('toggleSubheader'); } </script>
4. 父组件多余导入清理
父组件中import Child from './components/Header.vue';属于重复导入,直接删除即可。
修改后的完整代码
App.vue
<script setup lang="ts"> import { RouterLink, RouterView } from 'vue-router'; import Header from './components/Header.vue'; import TopicBar from './components/Topicbar.vue'; import $ from 'jquery'; import { ref } from 'vue'; const subheaderstate = ref(false); function subslide(){ subheaderstate.value = !subheaderstate.value; if(subheaderstate.value){ $('#topicbar').slideUp(); } else{ $('#topicbar').slideDown(); } } </script> <template> <header> <Header @toggle-subheader="subslide"/> </header> <div id="topicbar"> <TopicBar/> </div> </template>
Header.vue
<script setup lang="ts"> import $ from 'jquery'; const emit = defineEmits(['toggleSubheader']); function flip(){ const $arrow = $("#header_arrow"); const isFlipped = $arrow.hasClass("flipp"); if(isFlipped) { $arrow.removeClass("flipp"); $arrow.css({"transform":"rotate(0deg)", "transition-duration":"1s"}); } else{ $arrow.addClass("flipp"); $arrow.css({"transform":"rotate(180deg)", "transition-duration":"1s"}); } } function sub(){ emit('toggleSubheader'); } </script> <template> <h1 id="header_icon">Limits</h1> <input type="text" id="header_search" placeholder="Search posts and communities..."/> <div id="header_contact">Contact</div> <div id="header_topics" @click="flip(); sub();">Topics<img id="header_arrow" class="arrow flipp" src="./assets/down.svg" alt="down"></div> <div id="header_about">About Us</div> <div id="header_login">Login</div> <div id="header_signup">Sign Up</div> </template>
内容的提问来源于stack exchange,提问作者Cenek
相关产品推荐
相关产品推荐

