美文网首页
四、抽离左侧导航栏及路由

四、抽离左侧导航栏及路由

作者: 风之伤_3eed | 来源:发表于2019-12-10 10:27 被阅读0次

    一、新建src/config文件夹

    在文件夹下新建permission.tsx 文件
    (抽离导航及路由是为了方便将来根据后台返回用户权限来动态显示页面导航及路由)
    在pages文件下新建对应的页面文件,在config/permission.tsx文件中引入

    import {
      Dashboard,
      User,
      Magic,
      Setting
    } from '../pages';
    

    定义左侧导航属性类型

    // 左侧导航ts类型
    interface pageConfig {
      icon?: JSX.Element; //左侧导航图标
      key: string; //左侧导航唯一键
      title: string; //左侧导航名称
      MenuItem?: Array<pageConfig>; // 二级导航子列表
      dom?: () => any; // 该导航栏对应的页面(只对应一级路由的页面,二级路由对应页面由一级路由页面内管控)
    }
    

    只有一级路由导航配置

    const dashBoard:pageConfig = {
      icon: <Icon icon="dashboard" />,
      key: 'dashboard',
      title: '控制台',
      dom: Dashboard
    }
    

    二级路由导航配置

    const magic:pageConfig = {
      icon: <Icon icon="magic" />,
      key: 'magic',
      title: '角色类别',
      dom: Magic,
      MenuItem: [
        {
          key: 'warrior',
          title: '战士'
        },
        {
          key: 'assassin',
          title: '刺客'
        },
        {
          key: 'master',
          title: '法师'
        },
        {
          key: 'adc',
          title: 'ADC'
        },
        {
          key: 'Tank',
          title: '坦克'
        },
        {
          key: 'auxiliary',
          title: '辅助'
        }
      ]
    }
    

    导出时设置为数组方便操作

    const  navList = [
      dashBoard,
      user,
      magic,
      setting
    ]
    
    export default navList
    

    页面整体代码

    import React from 'react';
    import { Icon } from 'rsuite';
    import {
      Dashboard,
      User,
      Magic,
      Setting
    } from '../pages'; // 页面
    // 左侧导航ts类型
    interface pageConfig {
      icon?: JSX.Element;
      key: string;
      title: string;
      MenuItem?: Array<pageConfig>;
      dom?: any;
    }
    
    const dashBoard:pageConfig = {
      icon: <Icon icon="dashboard" />,
      key: 'dashboard',
      title: '控制台',
      dom: Dashboard
    }
    
    const user:pageConfig = {
      icon: <Icon icon="group" />,
      key: 'user',
      title: '用户中心',
      dom: User
    }
    
    const magic:pageConfig = {
      icon: <Icon icon="magic" />,
      key: 'magic',
      title: '角色类别',
      dom: Magic,
      MenuItem: [
        {
          key: 'warrior',
          title: '战士'
        },
        {
          key: 'assassin',
          title: '刺客'
        },
        {
          key: 'master',
          title: '法师'
        },
        {
          key: 'adc',
          title: 'ADC'
        },
        {
          key: 'Tank',
          title: '坦克'
        },
        {
          key: 'auxiliary',
          title: '辅助'
        }
      ]
    }
    
    const setting:pageConfig = {
      icon: <Icon icon="setting" />,
      key: 'setting',
      title: '角色设置',
      dom: Setting,
      MenuItem: [
        {
          key: 'skill',
          title: '技能修改'
        },
        {
          key: 'roles',
          title: '添加角色'
        },
      ]
    }
    
    const  navList = [
      dashBoard,
      user,
      magic,
      setting
    ]
    
    export default navList
    

    二、修改layout/index.tsx文件

    引入 permission 文件

    import { permission } from "../config";
    

    根据permission传递过来的值进行导航栏和路由匹配

    // 左侧导航栏
     const navList = permission.map((item: any, index: number) => {
       if (!item.MenuItem) {
         return (
           <Nav.Item eventKey={`/${item.key}`} key={index} icon={item.icon}>
             {item.title}
           </Nav.Item>
         );
       } else {
         const childrenList = item.MenuItem.map((item2: any, index2: number) => {
         return <Dropdown.Item eventKey={`/${item.key}/${item2.key}`} key={index2}>{item2.title}</Dropdown.Item>
         })
         return (
           <Dropdown
             key={index}
             eventKey={item.key}
             trigger="hover"
             title={item.title}
             icon={item.icon}
             placement="rightStart"
           >
             {childrenList}
           </Dropdown>
         );
       }
     });
    
     // 对应页面
     const page = permission.map((item, index) => {
       console.log(item)
       return <Route key={item.key} path={`/${item.key}`} component={item.dom} />
     })
    

    layout/index.tsx整体代码

    import React, { useState } from "react";
    import {
      Container,
      Header,
      Content,
      Nav,
      Navbar,
      Dropdown,
      Icon,
      Sidebar,
      Sidenav,
      Breadcrumb
    } from "rsuite";
    import { Route } from "react-router-dom";
    import { permission } from "../config";
    import "rsuite/lib/styles/index.less";
    import "./style.css";
    
    const headerStyles: any = {
      padding: 18,
      fontSize: 16,
      height: 56,
      background: "#34c3ff",
      color: " #fff",
      whiteSpace: "nowrap",
      overflow: "hidden"
    };
    
    const iconStyles: any = {
      width: 56,
      height: 56,
      lineHeight: "56px",
      textAlign: "center"
    };
    
    const NavToggle = ({ expand, onChange }: any) => {
      return (
        <Navbar appearance="subtle" className="nav-toggle">
          <Navbar.Body>
            <Nav>
              <Dropdown
                placement="topStart"
                trigger="click"
                renderTitle={children => {
                  return <Icon style={iconStyles} icon="cog" />;
                }}
              >
                <Dropdown.Item>帮助</Dropdown.Item>
                <Dropdown.Item>设置</Dropdown.Item>
                <Dropdown.Item>退出登陆</Dropdown.Item>
              </Dropdown>
            </Nav>
    
            <Nav pullRight>
              <Nav.Item
                onClick={onChange}
                style={{ width: 56, textAlign: "center" }}
              >
                <Icon icon={expand ? "angle-left" : "angle-right"} />
              </Nav.Item>
            </Nav>
          </Navbar.Body>
        </Navbar>
      );
    };
    
    interface Props {
      history: any;
      location: any;
    }
    
    const Home = (props: Props) => {
      const initActiveKey =
        props.location.pathname === "/" ? "/dashboard" : props.location.pathname; // 默认选中导航条
      console.log(initActiveKey);
      const initOpenKeys = props.location.pathname.split("/")[1]; // 默认打开的导航条
      const [expand, setExpand] = useState<boolean>(true);
      const [activeKey, setActiveKey] = useState(initActiveKey); // 决定当前选中的导航条;
      const [defaultOpenKeys, setDefaultOpenKeys] = useState(initOpenKeys); // 决定当前打开的导航条
      const handleToggle = () => {
        setExpand(!expand);
      };
    
      const onSelect = (eventKey: any, event: any) => {
        let newEventKey = eventKey;
        if (eventKey === "/dashboard") {
          newEventKey = "/";
        }
        setActiveKey(eventKey);
        const initOpen = eventKey.split("/");
        setDefaultOpenKeys(initOpen[1]);
        props.history.push(`${newEventKey}`);
      };
    
      // 左侧导航栏
      const navList = permission.map((item: any, index: number) => {
        if (!item.MenuItem) {
          return (
            <Nav.Item eventKey={`/${item.key}`} key={index} icon={item.icon}>
              {item.title}
            </Nav.Item>
          );
        } else {
          const childrenList = item.MenuItem.map((item2: any, index2: number) => {
            return (
              <Dropdown.Item eventKey={`/${item.key}/${item2.key}`} key={index2}>
                {item2.title}
              </Dropdown.Item>
            );
          });
          return (
            <Dropdown
              key={index}
              eventKey={item.key}
              trigger="hover"
              title={item.title}
              icon={item.icon}
              placement="rightStart"
            >
              {childrenList}
            </Dropdown>
          );
        }
      });
    
      // 对应页面
      const page = permission.map((item, index) => {
        if (item.key === "dashboard") {
          return <Route exact key={item.key} path={`/`} component={item.dom} />;
        }
        return <Route key={item.key} path={`/${item.key}`} component={item.dom} />;
      });
    
      let BreadcrumbList: any = {}; // 用来存放路由所对应的标题title
      for (var value of permission) {
        BreadcrumbList[value.key] = value.title;
        if (value.MenuItem) {
          value.MenuItem.map((item, index) => {
            BreadcrumbList[item.key] = item.title;
          });
        }
      }
    
      // 自动匹配当前路由自动生成面包屑导航
      let BreadcrumbName = props.location.pathname
        .split("/")
        .filter((item: any) => item)
        .map((item: any, index: number) => {
          return (
            <Breadcrumb.Item key={item}>{BreadcrumbList[item]}</Breadcrumb.Item>
          );
        });
    
        // 将dashobard页面设置为默认/地址
          console.log(props.location.pathname);
      if (props.location.pathname === "/") {
        console.log(BreadcrumbList);
        BreadcrumbName = (
          <Breadcrumb.Item key={"dashboard"}>
            {BreadcrumbList["dashboard"]}
          </Breadcrumb.Item>
        );
      }
    
      return (
        <div className="show-fake-browser sidebar-page">
          <Container>
            <Sidebar
              style={{ display: "flex", flexDirection: "column" }}
              width={expand ? 260 : 56}
              collapsible
            >
              <Sidenav.Header>
                <div style={headerStyles}>
                  <Icon
                    icon="logo-analytics"
                    size="lg"
                    style={{ verticalAlign: 0 }}
                  />
                  <span style={{ marginLeft: 12 }}> BRAND</span>
                </div>
              </Sidenav.Header>
              <Sidenav
                expanded={expand}
                defaultOpenKeys={[defaultOpenKeys]}
                appearance="subtle"
                onSelect={onSelect}
                activeKey={activeKey}
              >
                <Sidenav.Body>
                  <Nav>{navList}</Nav>
                </Sidenav.Body>
              </Sidenav>
              <NavToggle expand={expand} onChange={handleToggle} />
            </Sidebar>
    
            <Container>
              <Header>
                <Breadcrumb className="breadcrumb_ol">{BreadcrumbName}</Breadcrumb>
              </Header>
              <Content>{page}</Content>
            </Container>
          </Container>
        </div>
      );
    };
    
    export default Home;
    

    点击左侧导航栏即可切换路由显示对应页面(仅一级路由有效)

    三、在页面中设置二级路由

    前面只完成一级路由的跳转,二级路由的跳转在一级路由页面来完成。
    在src/pages/setting下新增roles和skill文件(仅用来展示页面内容)
    修改src/pages/setting/index.tsx文件

    import React from 'react';
    import { Route } from 'react-router-dom';
    import Skill from './skill'; //二级页面
    import Roles from './roles'; //二级页面
    
    const routes = [
      {
        id: 'skill',
        dom: Skill,
      },
      {
        id: 'roles',
        dom: Roles,
      }
    ];
    
    interface Props {
      match: any;
    }
    
    const Setting = (props: Props) => {
      const domList = routes.map((item, index) => {
        return <Route exact key={item.id} path={`${props.match.url}/${item.id}`} component={item.dom} />;
      })
    
      return domList
    }
    
    export default Setting
    

    其他拥有二级页面的设置类似
    至此可以根据左侧导航栏点击切换至相应页面

    相关文章

      网友评论

          本文标题:四、抽离左侧导航栏及路由

          本文链接:https://www.haomeiwen.com/subject/oelbgctx.html