Vue3路由页面重复添加Socket.IO事件监听器导致消息重复处理问题
Vue3路由页面重复添加Socket.IO事件监听器导致消息重复处理问题
嘿,这个问题我之前做Vue3项目时也碰到过!核心原因很直白:你每次进入这个路由页面,都会在setup里给Socket.IO的new_insert事件绑定一个新监听器,但离开页面(组件卸载)时没把旧监听器移除,次数多了就堆了一堆重复的监听器,每次收到消息就会触发所有已存在的监听器,自然就出现重复打印的情况了。
给你一个最直接的解决办法,用Vue3的生命周期钩子来清理监听器:
你得把事件回调单独存成变量,然后在组件卸载时(用onUnmounted钩子)调用Socket.IO的off方法移除对应的监听器。修改后的代码如下:
<script lang="ts"> import { socket } from "../services/socket"; import { onUnmounted } from 'vue'; export default { setup () { // 把回调单独存成变量,保证引用唯一,方便后续移除 const handleNewInsert = (inserted_id: number) => { console.log(inserted_id) } // 绑定监听器 socket.on('new_insert', handleNewInsert) // 组件卸载时移除对应的监听器 onUnmounted(() => { socket.off('new_insert', handleNewInsert) }) }, }; </script>
这里要注意个关键细节:绝对不能用匿名函数当监听回调。因为每次创建的匿名函数都是全新的引用,调用socket.off时传入匿名函数的话,Socket.IO找不到匹配的监听器,就没法完成移除操作,所以必须把回调存成固定变量。
如果你的场景是多个页面都需要监听new_insert事件,还可以换个思路:在services/socket.ts里给Socket.IO做一层封装,用Vue的响应式状态(比如ref或reactive)传递消息,各个组件只订阅这个响应式状态的变化,这样就不会出现重复绑定监听器的问题。不过针对你当前只有单个页面需要处理的情况,上面的方案就足够解决问题了。
备注:内容来源于stack exchange,提问作者ManiMatter
相关产品推荐
相关产品推荐

