组件内$on监听器能否监听mixin的$emit?全局mixin广播事件失效求解
关于Vue混入(Mixin)中$emit与组件$on监听的问题
没问题,我来给你理清楚这个事儿!
核心结论:组件$on完全可以监听混入的$emit事件
组件里的$on完全能捕获来自混入中$emit触发的自定义事件。原因很简单:混入的方法(包括foo)最终会被合并到组件的实例对象中,混入代码里的this指向的就是当前组件实例——也就是说,this.$emit('my-change')本质上是在组件自己身上触发事件,组件用this.$on监听自己的事件,自然是有效的。
为什么你的监听没生效?时机问题!
你遇到的created/mounted监听失效的问题,核心是事件触发的时机早于监听注册的时机。
Vue的混入钩子执行顺序是固定的:
- 混入的
beforeCreate→ 组件的beforeCreate - 混入的
created→ 组件的created - 混入的
mounted→ 组件的mounted
如果你的混入是在自身的created钩子中调用了foo方法触发事件,那此时组件的created还没执行,$on监听还没注册,事件已经触发完了,自然捕获不到。
解决方案:调整时机匹配
根据你的场景,有两种可靠的解决方式:
方式1:组件提前到beforeCreate注册监听
把组件的监听逻辑放到beforeCreate钩子中,这样在混入的created触发事件时,监听已经注册完成:
// 全局混入 Vue.mixin({ created() { this.foo(); // 混入的created先执行,但组件的beforeCreate已经注册了监听 }, methods: { foo() { this.$emit('my-change', 'bar'); } } }); // 组件代码 export default { beforeCreate() { this.$on('my-change', (e) => { console.log('收到事件:', e); // 会输出 "收到事件:bar" }); } };
方式2:混入中延迟触发事件
在混入的created里用$nextTick包裹事件触发逻辑,等待组件的created执行完成后再触发事件:
// 全局混入 Vue.mixin({ created() { this.$nextTick(() => { this.foo(); // 等待组件的created执行完,监听已注册 }); }, methods: { foo() { this.$emit('my-change', 'bar'); } } }); // 组件代码(依然用created监听) export default { created() { this.$on('my-change', (e) => { console.log('收到事件:', e); // 会输出 "收到事件:bar" }); } };
额外说明
如果你的foo方法不是在钩子中自动触发,而是通过用户交互(比如按钮点击)触发的,那不管组件在created还是mounted里监听都没问题——因为此时监听已经提前注册好了,事件触发在后。
内容的提问来源于stack exchange,提问作者Peter S
相关产品推荐
相关产品推荐

