路由

    下文介绍的路由使用可以在 umi-examples/routes 和 里找到示例代码。

    umi 会根据 目录自动生成路由配置。

    假设 pages 目录结构如下:

    那么,umi 会自动生成路由配置如下:

    1. [
    2. { path: '/': exact: true, component: './pages/index.js' },
    3. { path: '/users/': exact: true, component: './pages/users/index.js' },
    4. { path: '/users/list': exact: true, component: './pages/users/list.js' },
    5. ]

    动态路由

    umi 里约定,带 $ 前缀的目录或文件为动态路由。

    比如以下目录结构:

    1. + pages/
    2. + $post/
    3. - index.js
    4. - comments.js
    5. + users/
    6. $id.js
    7. - index.js

    会生成路由配置如下:

    1. [
    2. { path: '/': exact: true, component: './pages/index.js' },
    3. { path: '/users/:id': exact: true, component: './pages/users/$id.js' },
    4. { path: '/:post/': exact: true, component: './pages/$post/index.js' },
    5. { path: '/:post/comments': exact: true, component: './pages/$post/comments.js' },
    6. ]

    可选的动态路由

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

    比如以下结构:

    1. + pages/
    2. + users/
    3. $id$.js
    4. - index.js

    会生成路由配置如下:

    1. [
    2. { path: '/': exact: true, component: './pages/index.js' },
    3. { path: '/users/:id?': exact: true, component: './pages/users/$id$.js' },
    4. ]

    嵌套路由

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

    比如以下目录结构:

    1. + pages/
    2. + users/
    3. - _layout.js
    4. - $id.js
    5. - index.js

    会生成路由配置如下:

    1. [
    2. { path: '/users': exact: false, component: './pages/users/_layout.js'
    3. routes: [
    4. { path: '/users/', exact: true, component: './pages/users/index.js' },
    5. { path: '/users/:id', exact: true, component: './pages/users/$id.js' },
    6. ],
    7. },
    8. ]

    全局 layout

    umi 里约定 src 目录下的 layouts/index.js 为全局路由,返回一个 React 组件,通过 props.children 渲染子组件。

    你可能需要针对不同路由输出不同的全局 layout,umi 不支持这样的配置,但你仍可以在 layouts/index.js 对 location.path 做区分,渲染不同的 layout 。

    比如不想要针对 /login 输出简单布局,

    1. export default function(props) {
    2. if (props.location.pathname === '/login') {
    3. return <SimpleLayout>{ props.children }</SimpleLayout>
    4. }
    5. return (
    6. <>
    7. <Header />
    8. <Footer />
    9. </>
    10. );
    11. }

    404 路由

    umi 中约定 pages 目录下的 404.js 为 404 页面,需要返回 React 组件。

    比如:

    1. export default () => {
    2. return (
    3. <div>I am a customized 404 page</div>
    4. );
    5. };

    注:开发模式下,umi 会添加一个默认的 404 页面来辅助开发,但你仍然可通过精确地访问 /404 来验证 404 页面。

    路由过滤

    如果你需要在 下组织文件,那么有可能某些文件是不需要添加到路由的,那么你可以通过 umi-plugin-routes 插件进行排除。

    比如以下目录结构:

    1. + pages
    2. + users
    3. + models
    4. - a.js
    5. + services
    6. - a.js
    7. - index.js

    你应该只会想要 users/index.js 作为路由,所以需要排除掉 models 和 services 目录。

    先安装依赖,

    1. $ npm install umi-plugin-routes --save-dev

    然后配置 .umirc.js 如下:

    1. export default {
    2. plugins: [
    3. ['umi-plugin-routes', {
    4. exclude: [
    5. /models/,
    6. /services/,
    7. ],
    8. }],
    9. ]
    10. }

    权限路由

    umi 是通过配置定制化的 Route 组件来实现权限路由的,如果你熟悉 react-router@4,应该会比较熟悉。

    比如以下目录结构:

    1. + pages/
    2. - index.js
    3. - list.js

    然后在 .umirc.js 里做如下配置:

    1. export default {
    2. pages: {
    3. '/list': { Route: './routes/PrivateRoute.js' },
    4. // 如果你使用了动态路由,/products/$id.js 或者 /products/$id/index.js这种结构
    5. '/products/:id': { Route: './routes/PrivateRoute.js' },
    6. },
    7. }

    则会自动生成以下路由配置:

    ./routes/PrivateRoute.js 文件示例:

    1. import { Route } from 'react-router-dom';
    2. export default (args) => {
    3. const { render, ...rest } = args;
    4. return <Route
    5. {...rest}
    6. render={props =>
    7. <div>
    8. <div>PrivateRoute (routes/PrivateRoute.js)</div>
    9. {
    10. render(props)
    11. }
    12. </div>
    13. }
    14. />;
    15. }

    注:PrivateRoute 里渲染子组件是通过 render 方法,而非 Component 组件属性

    配置式路由

    umi 推荐的路由方式是基于目录和文件的约定的,但如果你倾向于使用配置式的路由,可以在 .umirc.js 里配置 routes ,此配置存在时则不会对 pages 目录做解析。

    比如:

    1. export default {
    2. routes: [
    3. { path: '/', exact: true, component: './components/a' },
    4. { path: '/list', component: './pages/b', Route: './routes/PrivateRoute.js' },
    5. { path: '/users', component: './pages/users/_layout',
    6. routes: [
    7. { path: '/users/detail', exact: true, component: './pages/users/detail' },
    8. { path: '/users/:id', exact: true, component: '/pages/users/id' }
    9. ]
    10. ],
    11. };

    注意:

    • component 为指向文件的相对路径,而非 React 组件
    • 支持通过 routes 实现嵌套路由
    • 支持通过 Route 指定权限路由

    路由动效应该是有多种实现方式,这里举 react-transition-group 的例子。

    先安装依赖,

    1. $ npm install react-transition-group --save

    在 layout 组件( 或者 pages 子目录下的 _layout.js)里在渲染子组件时用 TransitionGroup 和 CSSTransition 包裹一层,并以 location.key 为 key,

    1. import withRouter from 'umi/withRouter';
    2. import { TransitionGroup, CSSTransition } from "react-transition-group";
    3. export default withRouter(
    4. ({ location }) =>
    5. <TransitionGroup>
    6. <CSSTransition key={location.key} classNames="fade" timeout={300}>
    7. { children }
    8. </CSSTransition>
    9. </TransitionGroup>
    10. )

    上面用到的 fade 样式,可以在 src 下的 global.css 里定义:

    1. .fade-enter {
    2. opacity: 0;
    3. z-index: 1;
    4. }
    5. .fade-enter.fade-enter-active {
    6. opacity: 1;
    7. transition: opacity 250ms ease-in;
    8. }

    面包屑

    面包屑也是有多种实现方式,这里举 react-router-breadcrumbs-hoc 的例子。

    先安装依赖,

    1. $ npm install react-router-breadcrumbs-hoc --save

    然后实现一个 Breakcrumbs.js,比如:

    1. import NavLink from 'umi/navlink';
    2. import withBreadcrumbs from 'react-router-breadcrumbs-hoc';
    3. // 更多配置请移步 https://github.com/icd2k3/react-router-breadcrumbs-hoc
    4. const routes = [
    5. { path: '/', breadcrumb: '首页' },
    6. { path: '/list', breadcrumb: 'List Page' },
    7. ];
    8. export default withBreadcrumbs(routes)(({ breadcrumbs }) => (
    9. <div>
    10. {breadcrumbs.map((breadcrumb, index) => (
    11. <span key={breadcrumb.key}>
    12. <NavLink to={breadcrumb.props.match.url}>
    13. {breadcrumb}
    14. </NavLink>
    15. {(index < breadcrumbs.length - 1) && <i> / </i>}
    16. </span>
    17. ))}
    18. </div>
    19. ));

    然后在需要的地方引入此 React 组件即可。

    启用 Hash 路由

    umi 默认是用的 Browser History,如果要用 Hash History,需在 .umirc.js 里配置:

    Scroll to top

    1. import { Component } from 'react';
    2. import withRouter from 'umi/withRouter';
    3. class Layout extends Component {
    4. componentDidUpdate(prevProps) {
    5. if (this.props.location !== prevProps.location) {
    6. window.scrollTo(0, 0);
    7. }
    8. }
    9. render() {
    10. return this.props.children;
    11. }
    12. }

    参考