微前端乾坤(qiankun)的后台标签页功能实现

本文章仅记录我的开发历程,想要干货的请参考我下面的链接,本文可以略过了

react主应用增加tabs标签的逻辑

这里可以参考上面第一个链接,但是由于文章里的页面缓存实现是在父应用里实现的多例子应用,即每个页面都是一个单独的实例,页面多的情况下应该会有性能问题。所以只抄袭借鉴了这个文章里的tabs标签页的操作逻辑,页面缓存功能另寻出路。

子应用增加页面缓存

参考上面第二个链接,实现思路为在子应用unmount时,不调用vue或react的卸载事件,将rootDom append到document.body里面,并用样式隐藏,子应用重新mount时,将隐藏的rootDom显示

vue子应用

入口改造

ts 复制代码
let rootDom: Element | undefined;

async function render(props: any) {
  console.log("render");
  const { container } = props;
  const root = createApp(VueApp);
  root.use(createPinia());
  root.use(router);
  root.provide("appStore", props.appStore);
  rootDom = container ? container.querySelector("#root") : document.getElementById("root");
  root.mount(rootDom!);
}

renderWithQiankun({
  update() {},
  mount(props) {
    console.log("mount", props);
    props?.setLoading(false);
    if (!rootDom) {
      render(props);
    } else {
      rootDom!.setAttribute("display", "block");
      props.container?.parentNode?.appendChild(rootDom!);
    }
  },
  bootstrap() {
    console.log("bootstrap");
  },
  unmount(props) {
    console.log("unmount", props);
    rootDom!.setAttribute("display", "none");
    document.body.appendChild<Element>(rootDom!);
  },
});

keep-alive实现

js 复制代码
//layout.vue 

<template>
  <RouterView v-slot="{ Component }">
    <KeepAlive v-show="canCache">
      <component :is="Component"></component>
    </KeepAlive>
    <component v-if="canCache" :is="Component"></component>
  </RouterView>
</template>

react子应用

入口改造

ts 复制代码
//请参考vue的

由于react没有原生的KeepAlive组件,使用的是react-activation来实现页面缓存功能,如果需要实现类似vue的maxAPI,可以参考这里

ts 复制代码
// layout.tsx
import { KeepAlive, useAliveController } from "react-activation";
const MAX_CACHE = 10;
const keys: Set<string> = new Set();

const LayoutInner = () => {
  const routes = useLocation();
  const controller = useAliveController();

  const pushKeys = (key: string) => {
    const cachePath = keys.has(key);
    if (cachePath) {
      keys.delete(key);
      keys.add(key);
    } else {
      keys.add(key);
      if (keys.size > MAX_CACHE) {
        const deleteKey = keys.values().next().value;
        keys.delete(deleteKey);
        controller.drop(deleteKey);
      }
    }
  };
  const dom = <Outlet />;

  if (canCache)) {
    pushKeys(routes.pathname);
    return (
      <KeepAlive id={routes.pathname} name={routes.pathname}>
        {dom}
      </KeepAlive>
    );
  }
  return dom;
};

遇到的问题

  • vue子应用回退异常:原因是vue-router依赖了history.state,具体的原因请看这里
  • 场景:从子级页面增加一项数据,回到一级页面,由于做了页面缓存,新增的数据并不会出现在页面上,是一个合理的bug。合理的解决方案:参考ProTable - 高级表格 - ProComponents (ant.design)revalidateOnFocus,在窗口聚焦时重新请求接口
  • refreshTab刷新tab:原贴里使用了改变key的方式rerender页面,但是我们由于有页面缓存,页面加载时的接口等不会重新请求,还没有想到一个同时兼容vue和react的方案,暂时使用window.location.reload()代替
  • ......
相关推荐
大道归简1 小时前
案例:自动化获取Web页面小说(没钱修什么仙)——selenium
前端·selenium·自动化
Deepsleep.6 小时前
东田数码科技前端面经
前端·科技·面试
涵信8 小时前
第十八节:开放性问题-Vue生态未来趋势
前端·vue.js·devops
牧杉-惊蛰8 小时前
css 数字从0开始增加的动画效果
前端·javascript·css
孤灯淡茶8 小时前
Fiori学习专题十五:Nested Views
前端·javascript·学习
green_pine_8 小时前
CSS学习笔记14——移动端相关知识(rem,媒体查询,less)
前端·css·笔记·学习·less
Monly218 小时前
Vue:el-table-tree懒加载数据
前端·javascript·vue.js
进取星辰9 小时前
16、路由守卫:设置魔法结界——React 19 React Router
前端·javascript·react.js
清羽_ls9 小时前
cURL 入门:10 分钟学会用命令行发 HTTP 请求
前端·curl·命令行工具
jjw_zyfx9 小时前
vue3 css模拟语音通话不同语音、正在加载等的效果
前端·css