# UmiJS_路由

umi 会根据 pages 目录自动生成路由配置,当然也可以通过设置根目录的.umirc.js来引导路由

# 约定式路由

# 1.1 基础路由

例如 page 文件夹下是如下目录

├── tradecompetition
│   └── in.js
└── user
    └── login.js

那会自动生成如下路由配置

[
    {path: '/user/login', component: './pages/user/login.js'}
    {path: '/tradecompetition/in', component: './pages/tradecompetition/in.js'}
]

# 1.2 动态路由

umi 里约定,带$前缀的目录或文件为动态路由。 比如如下目录结构:

│page
├── $post/
│   ├──index.js
│   └──comments.js
└── user
    └── $id.js

会产生如下路由

[
  { path: "$post/", component: "./pages/$post/index.js" },
  { path: "$post/comments", component: "./pages/$post/comments.js" },
  { path: "user/:id", component: "./pages/user/$id.js" },
];

# 1.3 可选动态路由

umi 里约定动态路由如果带$后缀,则为可选动态路由。

└── user
    └── $id$.js
=>
[
    {path: '/user/:id?', component: './pages/user/$id$.js'}
]

# 1.4 嵌套路由

umi 里约定目录下有_layout.js时会生成嵌套路由,以_layout.js为该目录的 layout.

└── user
    ├── _layout.js
    ├── $id.js
    └── index.js
=>
[
    {
        path: '/user', component: './pages/user/_layout.js',
        routes: [
            {path: '/user/', component: './pages/user/index.js'},
            {path: '/user/$id', component: './pages/user/$id.js'},
        ]
    }
]

# 1.5 全局 layout

约定 src/layouts/index.js 为全局的路由,返回一个 React 组件,通过props.children渲染子组件 也可以根据 url 来渲染不同的取全局 layout

export default function(props) {
  if (props.location.pathname === "/login") {
    return <SimpleLayout> {props.children} </SimpleLayout>;
  }
  return (
    <div>
      <Header />
      {props.children}
      <Footer />
    </div>
  );
}

# 1.6 404 路由

umi 约定pages/404.js为 404 页面,需返回 React 组件 tips: 开发模式下,umi 会添加一个默认的 404 来辅助开发,不过可以通过/404来验证 404 页面。

# 1.7 通过注释扩展路由

 index.js
 /**
 * title: Index Page
 * Routes:
 *   - ./src/routes/a.js
 *   - ./src/routes/b.js
 */
 =>
 [
  { path: '/', component: './index.js',
    title: 'Index Page',
    Routes: [ './src/routes/a.js', './src/routes/b.js' ],
  },
]

# 配置式路由

设置根目录的.umirc.js来配置路由

export default {
    ...,
    routes: [
        {
            path: `/user/login`,
            component: `user/login`,
        },
        {
            path: `/tradecompetition/`,
            redirect: `/tradecompetition/index`,
        },
        {
            path: `/tradecompetition/index`,
            component: './tradecompetition/in',
        },
    ],
}

# 权限路由

umi 通过 Routes 属性来实现

[
  {
    path: "/list",
    component: "./pages/list.js",
    Routes: ["./routes/PrivateRoute.js"],
  },
];
// 用 ./routes/PrivateRoute.js 渲染 /list
export default (props) => {
  return (
    <div>
      <p>routes/PrivateRoute</p>
      {props.children}
    </div>
  );
};

# 路由动效

这里用react-transition-group

yarn add react-transition-group
layouts/index.js
import withRouter from 'umi/withRouter';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
export default withRouter(
    ({location})=>
    <TransitionGroup>
        <CSSTransition key={location.pathname} classNames = 'fade' timeout={300}>
            { children }
        </CSSTransition>
    </TransitionGroup>
)
//src/global.css
.fade-enter {
  opacity: 0;
  z-index: 1;
}

.fade-enter.fade-enter-active {
  opacity: 1;
  transition: opacity 250ms ease-in;
}

# 面包屑

这里用插件 react-router-breadcrumbs-hoc

yarn add react-router-breadcrumbs-hoc

Breakcrumbs.js

import NavLink from 'umi/navlink';
import withBreadcrumbs from 'react-router-breadcrumbs-hoc';

// 更多配置请移步 https://github.com/icd2k3/react-router-breadcrumbs-hoc
const routes = [
  { path: '/', breadcrumb: '首页' },
  { path: '/list', breadcrumb: 'List Page' },
];

export default withBreadcrumbs(routes)(({ breadcrumbs }) => (
  <div>
    {breadcrumbs.map((breadcrumb, index) => (
      <span key={breadcrumb.key}>
        <NavLink to={breadcrumb.props.match.url}>
          {breadcrumb}
        </NavLink>
        {(index < breadcrumbs.length - 1) && <i> / </i>}
      </span>
    ))}
  </div>
));

# Scroll to top

在 layout 里的 componentDidUpdata 里决定是否要 scroll to top

import { Component } from "react";
import withRouter from "umi/withRouter";

class Layout extends Component {
  componentDidUpdate(prevProps) {
    if (this.props.location !== prevProps.location) {
      window.scrollTo(0, 0);
    }
  }
  render() {
    return this.props.children;
  }
}

export default withRouter(Layout);

# 页面跳转

声明式

import Link from "umi/link";
export default () => <Link to="/list">Go to list page</Link>;

命令式

import router from "umi/router";
function goToListPage() {
  router.push("/list");
}