1

背景介绍

接上一篇《使用umi.js 3.0搭建React开发框架》(查看),我们在文中实现了React开发环境的基本实现,但是在用umi3.0搭建React项目时通常需要如下的功能:一个全局的菜单,可以一直显示,点击后可以跳转到不同的页面。具体的实现效果如下图所示,本文就该问题做简单的介绍

实现效果

功能拆解

可以将以上的需求拆分成如下的几个功能

  1. 构建全局的layout界面
  2. 能够实现路由跳转
  3. 能够在全局layout中根据路由配置生成具体的菜单

实现步骤

Step 1: 构建全局layout 官方参考文档

image.png
在src/文件夹下按照上图所示建立layouts文件夹及index.js文件

建立完成后输入如下代码:

export default withRouter(({ children, location }) => {
  
  return (
    <div>
      
      <div>
        <Switch location={location}>{children.props.children}</Switch>
      </div>
    </div>
  );
});

同时在.umirc.ts中做如下配置

routes: [
  {
    path: '/',
    component: '@/layouts/index',
    routes: [
      {
        exact: true,
        path: '/Demo1',
        name: 'Demo1',
        component: '@/pages/Demo1/index',
        icon: 'SettingOutlined',
      },
      {
        exact: true,
        path: '/Demo2',
        name: 'Demo2',
        component: '@/pages/Demo2/index',
        icon: 'AppstoreOutlined',
      },
    ],
  },
];

结合这两部分我们可以实现全局路由调整,umi.js在调整时首先载入@/layouts/index组件,即我们刚刚定义的全局的layout,然后再调整到具体的路由载入另一个页面。

实现了全局路由跳转后,问题在于我们要路由跳转只能手动在浏览器上输入路由,于是我们需要在全局layout中加入一个菜单方便我们跳转。

Step2: 根据路由配置构建菜单

此处的菜单使用antd 的Menu组件来实现,其界面效果如下
image.png

我们根据路由配置信息结合Menu组件的参数配置使用动态生成的方式实现,具体代码如下:

import React, { Fragment, useState } from 'react';
import { withRouter, Switch, history } from 'umi';
import { Menu } from 'antd';
import * as Icon from '@ant-design/icons';
import routerConfig from '../../config/router.config';

const { SubMenu } = Menu;

const getIcon = (iconName) => {
  const res = React.createElement(Icon[iconName], {
    style: { fontSize: '16px' },
  });
  return res;
};

const getSubMenu = (routesData) => {
  routesData.map((item) => {
    return <Menu.Item key={item.path}>{item.name}</Menu.Item>;
  });
};

const getMenu = (routesData) => {
  const menuData = [];
  for (let i = 0; i < routesData.length; i += 1) {
    if (Object.prototype.hasOwnProperty.call(routesData[i], 'routes')) {
      menuData.push(
        <SubMenu
          key={routesData[i].path}
          title={routesData[i].name}
          icon={getIcon(routesData[i].icon)}
        >
          {getSubMenu(routesData[i].routes)}
        </SubMenu>,
      );
    } else {
      menuData.push(
        <Menu.Item key={routesData[i].path} icon={getIcon(routesData[i].icon)}>
          {routesData[i].name}
        </Menu.Item>,
      );
    }
  }
  return menuData;
};
const CreateMenu = () => {
  const [levelOne] = routerConfig;
  const { routes } = levelOne;
  return <Fragment>{getMenu(routes)}</Fragment>;
};

export default withRouter(({ children, location }) => {
  const [current, setCurrent] = useState('');
  const handleClick = (e) => {
    history.push(e.key);
    setCurrent(e.key);
  };

  return (
    <div>
      <Menu onClick={handleClick} selectedKeys={[current]} mode="horizontal">
        {CreateMenu()}
      </Menu>
      <div>
        <Switch location={location}>{children.props.children}</Switch>
      </div>
    </div>
  );
});

其中getMenu函数是构建菜单的具体实现函数。

具体的demo可以参考


深圳飘
55 声望40 粉丝

暂时没有啥介绍的。