阅读视图

发现新文章,点击刷新页面。

Vben Admin管理系统集成微前端wujie-(三)终

  1. # Vben Admin管理系统集成qiankun微服务(一)
  2. # Vben Admin管理系统集成qiankun微服务(二)

一、前言

本篇是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文件即可

image.png 在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,

image.png

为测试在子应用状态保持,我在页面中添加一个测试文本框 ,测试内容不会随着切tab页签而重新加载,浏览器的前进后退也不会出错。

image.png

上述功能已集成在前端程序里,如果我的文章对你有帮助,感谢给我点个🌟

❌