Vben Admin管理系统集成微前端wujie-(三)终
一、前言
本篇是vben前端框架集成微服务的第3篇,前段时间写了vue-vben-admin集成qiankun的两篇文章,收到了大家不少建议,文章还遗留了一个问题就是多tab标签不支持状态保持,借助AI虽然也实现的相应方案,但是对vben的package包修改内容较多(后续同步主框架较为繁琐),并且修改代码健状性不好评估。抱歉暂停了进一步完善实现方案,目前先保持基本功能是ok。
近期也尝试wujie微前端框架发现能满足我当前的所有诉求,所以有了本篇的文章内容,前两篇文章的功能和问题在本文中都已支持,选择wujie原因是支持以下两个功能:
- 天然支持保活模式alive=true,与vben中route中Keeplive参数绑定,能支持状态保持的配置。
- wujie实现逻辑是iframe框架模式,对子应改造较小,如果不要支持主应用传参子应用可以不用改造或少量改造。
下面分步实施集成功能:
二、主应用调整
1.安装wujie和wujie-vue3
# 安装wujie
pnpm i wujie
# 安装wujie-vue3
pnpm i wujie-vue3
2. 清除沙箱数据实现
主应用src下添加wujie文件夹并添加index.ts文件,两个函数实现功能是清理沙箱缓存数据,保证在”退出登录重新打开“样式不会异常,refreshApp函数为后续单个页签关闭提供备用支持。
index.ts,文件内容如下:
interface HTMLIframeElementWithContentWindow extends HTMLIFrameElement {
contentWindow: Window;
}
// refreshApp 主应用可以通过下述方法,主动清除指定子应用的沙箱缓存
const refreshApp = (name = '') => {
if (!name) {
console.error('refreshApp方法必须传入子应用的name属性');
return;
}
// 这里的window应该是顶级窗口,也就是主应用的window
const SUB_FRAME = window.document.querySelector(
`iframe[name=${name}]`,
) as HTMLIframeElementWithContentWindow;
if (!SUB_FRAME) {
console.warn(`未找到${name}子应用,跳过刷新`);
return;
}
const SUB_WINDOW = SUB_FRAME.contentWindow;
const SUB_IDMAP = SUB_WINDOW.__WUJIE?.inject?.idToSandboxMap; // 沙箱Map对象
SUB_IDMAP.clear();
};
// 主应用中清除所有已激活的子应用沙箱缓存
const refreshAllApp = () => {
// 找到所有无界子应用的iframe
const ALL_SUB_IFRAME = window.document.querySelectorAll(
'iframe[data-wujie-flag]',
);
if (ALL_SUB_IFRAME.length === 0) {
console.warn('未找到任何子应用,跳过刷新');
return;
}
// 拿到这些iframe里面的contentWindow
const ALL_SUB_WINDOW = [...ALL_SUB_IFRAME].map(
(v) => (v as HTMLIframeElementWithContentWindow).contentWindow,
);
// 依次执行清除
ALL_SUB_WINDOW.forEach((v) => v.__WUJIE?.inject?.idToSandboxMap?.clear());
};
export { refreshAllApp, refreshApp };
主应用/src/layouts/basic.vue 程序主界面,在头部引入上述文件并在相应位置调用清除沙箱方法
# 引用
import { refreshAllApp } from '#/wujie/index';
# 退出时清理
// logout
async function handleLogout() {
await authStore.logout(false);
refreshAllApp();
}
3. 添加微服务通用页面wujie.vue
在主应用 /apps/web-caipu/src/views/_core下添加wujie.vue页面,页面内容如:
<script setup lang="ts">
import { ref } from 'vue';
import { useRoute } from 'vue-router';
import { preferences } from '@vben/preferences';
import { useAccessStore, useUserStore } from '@vben/stores';
import WujieVue from 'wujie-vue3';
const useStore = useUserStore();
const accessStore = useAccessStore();
const route = useRoute();
// props通信
const props = ref({
userinfo: useStore.userInfo,
token: accessStore.accessToken,
preferences,
});
// 加时缀是强制刷新
const appUrl = ref(`http://localhost:5667/app${route.path}?t=${Date.now()}`);
const keepLive = route.meta?.keepAlive;
</script>
<template>
<div class="sub-app-container">
<WujieVue
width="100%"
height="100%"
:name="appUrl"
:url="appUrl"
:alive="keepLive"
:props="props"
/>
</div>
</template>
<style scoped>
.sub-app-container {
width: 100%;
height: 100%;
background: white;
}
</style>
<style scoped>
.sub-app-container {
width: 100%;
height: 100%;
overflow: hidden;
background: white;
border-radius: 8px;
}
</style>
聪明的你,一定知道实现的逻辑。其中子应用的地址测试写localhost:5667,后面会集成配置文件中,至此主应用改造完成。
三、子应用改造
子应用基本不用改,只要改/Users/wgh/code/caipu-vben-admin/apps-micro/web-antd/src/bootstrap.ts文件即可
在49行添加如下代码,代码不用解释,之前一样的实现逻辑。
// 初使化存储之后赋值,避免路由判断跳转到登录页
if (window.__POWERED_BY_WUJIE__) {
// props 接收
const props = window.$wujie?.props; // {data: xxx, methods: xxx}
const useStore = useUserStore();
const accessStore = useAccessStore();
useStore.setUserInfo(props.userInfo);
accessStore.setAccessToken(props.token);
updatePreferences(props.preferences);
// window.$wujie?.bus.$on('wujie-theme-update', (theme: any) => {
// alert('wujie-theme-update');
// updatePreferences(theme);
// });
window.addEventListener('wujie-theme-update', (theme: any) => {
updatePreferences(theme.detail);
});
}
四。新增路由配置
在主应用路由中配置子应用一个测试路由 /app/basic/test,
为测试在子应用状态保持,我在页面中添加一个测试文本框 ,测试内容不会随着切tab页签而重新加载,浏览器的前进后退也不会出错。
上述功能已集成在前端程序里,如果我的文章对你有帮助,感谢给我点个🌟
- 前端地址:caipu-vue-admin
- 后端地址:go-caipu