我刚刚在vuejs中使用事件总线来获取动态组件,但是当我从一个组件发出事件时,我无法在另一个组件中侦听该事件。下面是我通过codesandbox创建的演示,我想要做的是在tes2'中输出' test来自test2component,但它什么也没输出。但是当我在HomeCompnent中取消注释$ bus监听器时,两个console.log都被执行了。
Vue.propotype.$bus = new Vue();
<template>
<div>
<component :is="currentComponent" @changeComponent="changeComponent"></component>
</div>
</template>
<script>
import Test1Component from "./Test1Component";
import Test2Component from "./Test2Component";
export default {
created() {
// this.$bus.$on("test", () => console.log("event bus test"));
},
components: {
Test1Component,
Test2Component
},
data() {
return {
currentComponent: "Test1Component"
};
},
methods: {
changeComponent() {
this.currentComponent = "Test2Component";
}
}
};
</script>
<style>
</style>
<template>
<div>
<h1>test1</h1>
<button @click="changeComponent">click me</button>
</div>
</template>
<script>
export default {
methods: {
changeComponent() {
this.$emit("changeComponent");
this.$bus.$emit("test");
}
}
};
</script>
<style>
</style>
<template>
<h1>test2</h1>
</template>
<script>
export default {
created() {
this.$bus.$on("test", () => console.log("test in test2"));
}
};
</script>
<style>
</style>
答案 0 :(得分:2)
事件总线很好,但问题在于实施。
你是非常正确的un-comment code
在家庭组件中,我在你的代码片段上测试它只发出一次event bus test
[console.log]
您需要注意事件
在您的情况下,您在listener function $on
created
事件中撰写了Test2Component
现在就想想,开始时你没有任何听众,就像home compo
你刚刚评论过听众代码一样。[它的第一步]
现在,当您单击click me
按钮时,您changing
组件到新组件[Test2Component],它已挂载且其created
事件将触发then this listener will start listening to event
但你错过了
this.$emit("changeComponent"); // this is first [ fires/emit ]
this.$bus.$emit("test"); // THEN THIS EMIT
所以,当它刚从
changing
compo2compo1 to
测试同步
fired/emitted directly without wait, its not
A 同步{{ 1}} {changeComponent {1}} test`]
猜猜什么现在it is
发出时,It will not wait to finish all stuff of
,. It will be emitted immediately [
已发出
所以,
test
,所以没有Dom operation to add component, ITS NOT DONE YET
但是,如果您看到,test
之前家庭功能监听器中的No listeners are there
已经很好地定义,那么它将在控制台中输出。
我希望你理解它,如果不是让我知道,我会详细解释它
另一个问题是您在
console.log
中添加了$ bus,因此所有组件都有自己的总线。相反,您可以使用UNCOMMENT listener
例如你可以看到。
在es6中你可以做到
emit of test event
将其导入其他组件
prototype
GLOBAL event Bus
&#13;
//bus.js
const bus = new Vue({});
export default bus;
&#13;
答案 1 :(得分:1)
这个问题很好地证明了事件总线模式的缺点:
开发人员必须小心确保所有事件的发件人和收件人在同一时刻确实存在。
在您的方案中,情况并非如此:
我作为Vue核心团队成员的通常免责声明:不要使用事件总线模式。
答案 2 :(得分:0)
您的测试不正确。
基本上,在Test2Component
发出Test1Component
this.$bus.$emit("test");
您看到2个console.log,因为codesandbox使用热重装模块,因此如果您更改代码,this.$bus.$on("test", () => console.log("test in test2"));
仍会注册。
如果在Test2Component
中销毁组件时取消注册,test in test2
永远不会被记录
<强> Test2Component.vue 强>
<template>
<div>
<h1>test2</h1>
<button @click="changeComponent">click me</button>
</div>
</template>
<script>
export default {
created() {
console.log("Component 2 is created");
this.$bus.$on("test", this.testLog);
},
beforeDestroy() {
this.$bus.$off("test", this.testLog);
},
methods: {
testLog() {
console.log("test in test2");
},
changeComponent() {
this.$emit("changeComponent");
}
}
};
</script>
<style>
</style>
演示:https://codesandbox.io/s/2485jw460y
如果您发表评论
beforeDestroy() {
this.$bus.$off("test", this.testLog);
},
在组件2中,您会看到test in test2
在点击几下后多次打印
(如果您更改了代码,请刷新以便从头开始运行)