vue3 中 iframe 多页面切换导致资源刷新的问题解决
最近发现一个问题,我在使用 websocket 的时候,在主页面进行了 websocket 连接了之后,再使用 iframe 打开子页面的时候,通常会触发页面刷新,这样就导致 WebSocket 断开,这是因为切换 src 会重新加载 iframe 内容,使得页面环境重置,进而导致 WebSocket 连接丢失。
最近发现一个问题,我在使用 websocket 的时候,在主页面进行了 websocket 连接了之后,再使用 iframe 打开子页面的时候,通常会触发页面刷新,这样就导致 WebSocket 断开,这是因为切换 src 会重新加载 iframe 内容,使得页面环境重置,进而导致 WebSocket 连接丢失。
问题复现
页面
<div style="width: 100%; height: 100vh; position: fixed; display: flex; margin-top: 5px;left: 0;">
<div style="background: #EDEDED; width: 200px; height: 100%; margin: 0; display: inline-block;">
<el-row class="tac">
<el-col :span="12">
<el-menu style="width: 200px;background-color: #EDEDED" :unique-opened="true">
<el-sub-menu index="1">
<template #title>
<span>系统管理</span>
</template>
<el-menu-item style="background-color: #F7F7F7" index="1-1" @click="customerManagement">用户管理</el-menu-item>
</el-sub-menu>
<el-sub-menu index="2">
<template #title>
<span>即时通讯</span>
</template>
<el-menu-item style="background-color: #F7F7F7" index="2-1" @click="toContactListPage">联系人</el-menu-item>
<el-menu-item style="background-color: #F7F7F7; position: relative; display: flex; align-items: center;" index="2-2" @click="toMessagePage">消息</el-menu-item>
</el-sub-menu>
</el-menu>
</el-col>
</el-row>
</div>
<div style="width: 100%; height: 100vh; margin-left: 5px;">
<iframe style="background-color: white; width: 100%; height: 100vh; border: none;" :src="iframePage"></iframe>
</div>
</div>
导航
let iframePage = ref("/zecSystemManagement/DataScreen");
// 点击用户管理
const customerManagement = async() => {
iframePage.value = "/zecSystemManagement/UserManagementPage";
};
// 点击好友列表
const toContactListPage = async() => {
iframePage.value = "/zecInstantMessaging/ContactListPage";
};
// 点击消息
const toMessagePage = async() => {
iframePage.value = "/zecInstantMessaging/MessagePage";
};
websocket 连接
这个是 websocket.js 页面获取 websocket 实例的一个方法。
export async function getWebSocket() {
console.log(webSocket);
if (webSocket === undefined){
console.log("ddd");
// 连接 websocket 的方法
await connectWebSocket(getAccountBySessionStorage());
}
return webSocket;
}
打印
控制台打印的就是跳转页面后,获取 websocket 实例,调用 getWebSocket 方法。

可以看到这种写法很不好用,每次点击一个导航栏都会导致 websocket 重连,然后我苦心钻研两天半,发现了下面好用一点的写法。
问题解决
页面
上面导航栏的页面不变,下面的 iframe 使用 keep-alive 替代。
在 Vue.js 中,<keep-alive>是一个内置组件,用于缓存组件实例,避免重复渲染和销毁。
<div style="width: 100%; height: 100vh; margin-left: 5px;">
<!-- <iframe id="iframe" style="background-color: white; width: 100%; height: 100vh; border: none;" :src="iframePage"></iframe>-->
<keep-alive>
<component :is="currentComponent"></component>
</keep-alive>
</div>
导航
markRaw:用于标记一个对象,使其永远不会被 Vue 的反应式系统转换。
import ContactListPage from '@/module/zec-instant-messaging/views/ContactListPage';
import MessagePage from '@/module/zec-instant-messaging/views/MessagePage';
import UserManagementPage from '@/module/zec-system-management/views/UserManagementPage';
let iframePage = ref("/zecSystemManagement/DataScreen");
let currentComponent = ref(null);
// 点击用户管理
const customerManagement = async() => {
currentComponent.value = markRaw(UserManagementPage);
// iframePage.value = "/zecSystemManagement/UserManagementPage";
};
// 点击好友列表
const toContactListPage = async() => {
currentComponent.value = markRaw(ContactListPage);
// iframePage.value = "/zecInstantMessaging/ContactListPage";
};
// 点击消息
const toMessagePage = async() => {
currentComponent.value = markRaw(MessagePage);
// iframePage.value = "/zecInstantMessaging/MessagePage";
};
只需要换这两个地方。
展示

这样就解决了 iframe 多页面切换导致资源刷新的问题,websocket 也不会一直重连浪费资源。
如果有什么不妥或者更好的写法,也可以相互学习学习。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)