Vue动态组件中Event Bus无法正常工作的问题排查
Vue Event Bus 动态组件通信问题解决
我来帮你捋清楚这个问题的根源,以及对应的解决办法~
问题核心原因
你遇到的关键问题是事件触发时机和组件实例化时机不匹配:
当你在Test1Component点击按钮时,先执行this.$emit("changeComponent")切换组件,紧接着就触发this.$bus.$emit("test")。但Vue切换动态组件需要经历「销毁旧组件→创建新组件→挂载新组件」的异步过程——也就是说,当$bus.$emit("test")执行时,Test2Component还没被创建出来,它的created钩子还没执行,自然没注册上事件监听器,所以根本听不到这个事件。
而HomeComponent的监听器是在自身created钩子中注册的,从页面加载时就存在,所以能正常监听到事件。
另外还要提个小细节:你main.js里的Vue.propotype拼写错了,应该是Vue.prototype,虽然这个可能没影响当前功能,但修正后更规范。
解决方案
这里给你两种靠谱的解决思路:
方案1:延迟触发总线事件,等Test2Component创建完成后再发
把总线事件的触发时机放到组件切换完成之后,利用Vue的$nextTick确保新组件已经挂载完成:
- 修改Test1Component的方法,只负责触发组件切换:
<script> export default { methods: { changeComponent() { this.$emit("changeComponent"); // 移除这里的 this.$bus.$emit("test") } } }; </script>
- 在HomeComponent的切换方法中,用
$nextTick延迟触发总线事件:
<script> import Test1Component from "./Test1Component"; import Test2Component from "./Test2Component"; export default { // ...其他代码不变 methods: { changeComponent() { this.currentComponent = "Test2Component"; this.$nextTick(() => { // 等Test2Component创建挂载完成后再触发事件 this.$bus.$emit("test"); }); } } }; </script>
方案2:改用组件props传递(适合简单场景)
如果只是在组件切换时传递状态或触发通知,也可以不用Event Bus,直接通过动态组件的props传递信息:
- HomeComponent中添加状态,传递给Test2Component:
<template> <div> <component :is="currentComponent" @changeComponent="changeComponent" :triggerTest="triggerTest" ></component> </div> </template> <script> // ...其他代码不变 export default { data() { return { currentComponent: "Test1Component", triggerTest: false }; }, methods: { changeComponent() { this.currentComponent = "Test2Component"; this.$nextTick(() => { this.triggerTest = true; // 如果需要只触发一次,之后可以重置 setTimeout(() => this.triggerTest = false, 0); }); } } }; </script>
- Test2Component监听props变化:
<script> export default { props: ['triggerTest'], watch: { triggerTest(newVal) { if (newVal) { console.log("test in test2"); } } } }; </script>
验证效果
按照方案1修改后,Test2Component就能正常输出test in test2了,因为此时事件触发时,Test2的监听器已经注册完成。
内容的提问来源于stack exchange,提问作者ChenLee
相关产品推荐
相关产品推荐

