# cosmos-router


## 安装

  项目若未安装 cosmos-router，首先设置npm源地址为内部私服地址 http://10.188.40.249/  ，然后执行
  
  `npm install cosmos-router --save`
  

## cosmos-router 的功能

  1. 减少配置文件，通过一份config文件实现路由、菜单和面包屑的配置
  2. 路由层级和菜单层级保持一致
  3. 菜单项渲染和路由的权限保持一致
  4. 可配置动态的路由
  5. 自动生成菜单、面包屑
  6. 可不使用默认的页面布局

## 使用

  ```javascript
  import { CosmosRouter } from 'cosmos-router';

  // 定义路由配置
  const routeConfig = [{ path: '', name: '首页', auth: 1 }];
  // 定义Layout组件
  const Layout = ({ children }) => <div>{children}</div>;
  // 定义权限列表
  const authList = [1, 2, 3];

  <CosmosRouter routes={routerConfig}
    layout={Layout}
    lazyLoad={path => import('./pages' + path).catch((err) => {
      return { default: () => <div>页面不见了</div> };
    })}
    defaultConfig={{ // 路由配置项的默认值
      fallback: <div>loading</div>
    }}
    checkAuth={({ auth }) => authList.indexOf(auth) !== -1} // 校验权限的方法
    hasCheckResult={!!(authList && authList.length)} // 已从接口获取权限列表
  />
  ```

  类型定义
  ```typescript
  type CheckAuth = (config: RouteConfig) => boolean;

  interface CosmosRouterProps {
    /** 路由配置项数组 */
    routes: Routes;
    /** 默认的路由配置 */
    defaultConfig?: RouteConfig;
    /** 懒加载时引用组件的方法 */
    lazyLoad?: (path: string) => Promise<{ default: ComponentType; }>;
    /** 路由的布局组件 */
    layout?: ElementType;
    /** 校验权限的方法 */
    checkAuth?: CheckAuth;
    /** 校验结果是否已返回 */
    hasCheckResult?: boolean;
    /** 文件目录结构是否跟随路由结构，默认 false */
    catalogFromRoute?: boolean;
  };
  ```

  catalogFromRoute 为 true 时，项目目录为嵌套结构目录，为 false 时，项目目录为扁平结构。

## 配置项说明

  ```typescript
  interface RouteBaseConfig<Extend extends Record<string, unknown> = {}, Auth = number> extends RouteProps {
    path?: string;
    /** 重定向地址 */
    redirectTo?: string;
    /** 组件所在的目录，默认为路由的path */
    catalog?: string;
    /** 菜单的名称 */
    name?: string;
    /** 菜单的icon */
    icon?: string | ReactNode;
    /** 进入路由的权限 */
    auth?: Auth;
    /** 是否使用布局，默认 true */
    useLayout?: boolean;
    /** 子路由配置 */
    children?: RouteConfig<Extend, Auth>[];
    /** 加载失败时的内容 */
    fallback?: ReactNode;
    /** 有子路由时，自身是否为路由，默认 false */
    exist?: boolean;
  }
  ```

  - **普通的路由**

    ```typescript
    {
      path: 'homePage', // 路由的路径
      icon: 'iconside_home2x', // 根据此字段生成 Menu 的 Icon，默认 string 类型时为 Menu 的 type
      name: '首页' // 菜单和面包屑的名称
    }
    ```

    默认会根据path读取pages文件夹里的 HomePage 文件或 HomePage 文件夹里的 index 文件，路由地址为 /homePage 时渲染该组件

  - **自定义path，不和文件目录一致**

    ```typescript
    {
      path: 'home',
      catalog: 'HomePage', // 文件所在目录或文件名称，注意首字母大小写要和目录或文件一致
      icon: 'iconside_home2x',
      name: '首页'
    }
    ```

    catalog 项存在时，path不会为默认目录，会读取 catalog 的组件，以此实现 path 不同于目录结构

  - **子路由**

    ```typescript
    {
      path: 'demo',
      name: '路由测试',
      // exist: true, // 有子路由时默认父级不是路由，如果需要父级也作为路由，exist 设置为 true
      children: [ // 路由的子路由
        {
          path: 'child',
          name: '子路由'
        },
      ]
    }

    ```

    地址为 /demo/child 时会读取 pages/Demo/Child 文件或文件夹里的index文件，然后渲染default导出的组件

  - **动态路由**

    ```typescript
    {
      path: 'user',
      name: '用户列表',
      exist: true, // 此处必须为true，不然 /user 路由不存在
      children: [
        {
          path: ':userId',
          name: '用户详情',
          catalog: 'Info'
        }
      ]
    }
    ```

    地址为 /user 时渲染 User/index 组件，为 /user/1 时渲染 User/Info 组件，组件内通过 react-router-dom 内置的 useParams hook可以获取到 { userId: 1 };