umi+umi内置qiankun插件,基座和子应用的路由跳转和路由配置以及动态路由配置
在react项目还有vue项目中,我们被一种思想所固化,我相信现在还有很多人觉得路由就是左边菜单栏显示的菜单。但是这是错误的,这一个非常严重的误区,也是我在react作为基座的时候一直困扰我的一个点。
菜单和路由不应该完全的关联起来,二者没有必然的联系,在vue的框架中我们只需要配置了对应的router,对用的菜单也就出来了。所以让我们觉得路由就是菜单,菜单就是路由,其实框架层面为我们做了很多,让路由和菜单对应起来了,给了我们一个错觉让我们觉得菜单就是路由。其实二者没有什么直接联系。
比如在react中这是我们常用的配置路由方式按照一层一层的层级配置,然后在config中去引入route然后ant-design-pro内置layout插件自动帮我们识别路由形成我们需要的菜单。但是我们明白了菜单是菜单路由是路由,我们就有跟多的方式去实现。

{
    name: 'react子应用',
    path: '/antd',
    microApp: 'antd',
    routes: [
      {
        name: 'Welcome',
        icon: 'smile',
        path: '/antd/Welcome',
      },
      {
        name: 'table-list',
        icon: 'table',
        path: '/antd/oil',
      },
      {
        name: 'login',
        path: '/antd/user/loginAtion',
        hideInMenu: true,
      },
    ],
  }

可以在运行时配置里面去对menu做配置

export const route = [
  {
    name: 'react',
    path: '/antd',
    children: [
      {
        path: '/antd',
        redirect: '/antd/welcome',
      },
      {
        path: '/antd/welcome',
        name: '首页',
      },

      {
        name: '服务管理',

        path: '/antd/list',

        children: [
          {
            path: '/antd/list',
            redirect: '/antd/list/cluster/index',
          },
          {
            path: '/antd/list/cluster/index',
            name: '我的工单',
          },
          {
            path: '/antd/list/cluster/device',
            name: '设备列表',
          },
          {
            path: '/antd/list/cluster/list',
            name: '服务列表',
          },
        ],
      },
    ],
  },
];
 
menuDataRender: (menuData: MenuDataItem) => {
  return menuData.concat(route);
 }

动态路由,在umi运行时配置中这个函数去对动态路由做处理,比如引入component,这里完全不用按照层级路由的方式去递归嵌套,直接扁平处理路由,然后再菜单运行时配置去处理菜单的层级关系就可以了。

let extraRoutes;

export function patchRoutes({ routes }) {
  merge(routes, extraRoutes);
}

export function render(oldRender) {
  fetch('/api/routes').then(res=>res.json()).then((res) => { 
    extraRoutes = res.routes;
    oldRender();
  })
}

弄明白这些之后微前端配置不管是动态路由还是静态路由,就非常简单了。

基座应用中config配置

 qiankun: {
    master: {
      apps: [
        {
          name: 'antd',
          entry: '//localhost:8001',
        },
        {
          name: 'reactApp', // 唯一 id
          entry: 'http://localhost:8002', // html entry
        },
        {
          name: 'vueApp',
          entry: '//localhost:8092',
        },
      ],
    },
  },

子应用中config配置

qiankun: {
    slave: {},
  },

最重要的就是子应用的路由怎么在基座应用配置以及点击基座应用路由子应用怎么对应跳转
配置路由有两种方式,第一种是在路由文件中引入,比如加这个microApp,这个指的是子应用的名称在umi项目中子应用名称只要在config中配置了qiankun:{save:{}}默认都是package.json中的name名称作为项目的名称以及前缀base

{
    name: 'react子应用',
    path: '/antd',
    microApp: 'antd',
    routes: [
      {
        name: 'Welcome',
        icon: 'smile',
        path: '/antd/Welcome',
      },
      {
        name: 'table-list',
        icon: 'table',
        path: '/antd/oil',
      },
      {
        name: 'login',
        path: '/antd/user/loginAtion',
        hideInMenu: true,
      },
    ],
  },

这种方式就是在子应用有前缀的情况下可以自动匹配子应用所有路由,上面哪种方式需要一个一个路由对应的写出来

{ name: 'react', icon: 'table', path: '/antd/*', hideInMenu: true, microApp: 'antd' },

还可以通过组件的方式引入

import { MicroApp } from 'umi';
//基座有前缀的话就要加上这个base
export default function Page() {
  return <MicroApp name="antd" base="/antd" />;
}
//微前端这种方式通过microapp组件方式直接把微应用的路由地址放过来就可以直接关联上
//这里配置ant在microapp中要配置base路径不然没作用
  {
    name: 'reacte',
    icon: 'table',
    path: '/antd',
    component: './MicroApp',
    routes: [
      {
        path: '/antd',
        redirect: '/antd/welcome',
      },
      {
        path: '/antd/welcome',
        name: '首页',
      },
      
      {
        path: '/antd/list/cluster/index',
        name: '我的工单',
      },
      {
        path: '/antd/list/cluster/device',
        name: '设备列表',
      },
      {
        path: '/antd/list/cluster/list',
        name: '服务列表',
      },
    ],
  },



到这微前端的配置就全部完成,基座和子应用的传参方式我用的是官方提供的initClobalState
全局创建action.ts文件,在使用的地方分别引入

// in src\actions\index.js

import { initGlobalState } from 'qiankun';

const initialState = {
  //这里写初始化数据
  token: '测试',
  mes2: 0,
  app1Msg: 0, // 子应用app1的数据
};

// 初始化 state
const actions = initGlobalState(initialState);
actions.onGlobalStateChange((state, prev) => {
  //监听公共状态的变化
  console.log('主应用: 变更后');
  console.log(state);
});

export default actions;

实现token传递给子应用

 actions.setGlobalState({ token: data.token }); //通过setGlobalState改变全局状态

子应用中一样有action.ts直接在生命周期中获取token就可以实现免密登录了

export const qiankun = {
  // 应用加载之前
  async bootstrap(props: any) {
    console.log('app1 bootstrap', props);
  },
  // 应用 render 之前触发
  async mount(props: any) {
    actions.setActions(props);
    actions.onGlobalStateChange((state: Record<string, any>, prev: Record<string, any>) => {
      console.log('react子应用监听主应用发来的信息', state, prev);
      if (state?.token) {
        sessionStorage.setItem('aggregation', state.token);
      }
    }, true);
    console.log('app1 mount', props);
  },
  // 应用卸载之后触发
  async unmount(props: any) {
    console.log('app1 unmount', props);
  },
};

这个是基座项目的登录
这个是基座项目的登录
登录成功的主页面接入了react,vue的子项目
登录成功的主页面接入了react,vue的子项目

点击react项目完美实现免登还有路由跳转,后续的传参采用一样方法点击react项目完美实现免登还有路由跳转,后续的传参采用一样方法

感谢观看!一起在react知识的海洋中翱翔吧!

Logo

前往低代码交流专区

更多推荐