微前端乾坤(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()代替
  • ......
相关推荐
一 乐7 分钟前
民宿|基于java的民宿推荐系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·源码
testleaf36 分钟前
前端面经整理【1】
前端·面试
好了来看下一题38 分钟前
使用 React+Vite+Electron 搭建桌面应用
前端·react.js·electron
啃火龙果的兔子38 分钟前
前端八股文-react篇
前端·react.js·前端框架
小前端大牛马44 分钟前
react中hook和高阶组件的选型
前端·javascript·vue.js
刺客-Andy1 小时前
React第六十二节 Router中 createStaticRouter 的使用详解
前端·javascript·react.js
萌萌哒草头将军3 小时前
🚀🚀🚀VSCode 发布 1.101 版本,Copilot 更全能!
前端·vue.js·react.js
GIS之路3 小时前
OpenLayers 图层叠加控制
前端·信息可视化
90后的晨仔3 小时前
ArkTS 语言中的number和Number区别是什么?
前端·harmonyos
菜鸡爱上编程3 小时前
React16,17,18,19更新对比
前端·javascript·reactjs·react