Skip to content

约定式路由

Umi.js 是一个可插拔的企业级 react 应用框架,它内置了约定式路由(convention-based routing),使得开发者无需手动配置路由,只需要按照一定的文件和目录结构组织代码,Umi 就能自动解析并生成对应的路由配置。这种方式极大地简化了路由管理,特别是在大型项目中,能够显著提高开发效率。

约定式路由的工作原理

Umi.js 中,约定式路由的核心思想是根据页面组件所在的文件路径自动生成路由规则。默认情况下,Umi 会扫描 src/pages 目录下的文件,并将其转换为相应的路由。例如:

  • src/pages/index.jsx 对应 /
  • src/pages/users.jsx 对应 /users
  • src/pages/users/[id].jsx 对应 /users/:id

文件命名规则

Umi 的约定式路由支持多种文件命名规则来定义不同的路由行为:

  • 普通页面:直接以 .jsx.tsx 结尾的文件会被视为普通的页面组件。
  • 动态路由:使用方括号包裹参数名(如 [id])可以创建动态路由,用于匹配 URL 中的动态部分。
  • 布局页面:带有 _layout.jsx_layout.tsx 后缀的文件会被识别为布局组件,它可以包裹其他页面,提供统一的布局样式或功能。
  • 重定向:通过创建 _redirects.jsx_redirects.tsx 文件,你可以定义重定向规则。
  • 404 页面:创建名为 404.jsx404.tsx 的文件作为未找到页面时的默认显示内容。

示例

假设你有如下文件结构:

src/
├── pages/
│   ├── index.jsx
│   ├── users/
│   │   ├── index.jsx
│   │   └── [id].jsx
│   └── about.jsx
└── layouts/
    └── basicLayout.jsx

这将自动生成以下路由表:

路径组件布局
/src/pages/index.jsx-
/userssrc/pages/users/index.jsx-
/users/:idsrc/pages/users/[id].jsx-
/aboutsrc/pages/about.jsx-

如果想为所有页面添加一个公共的布局,可以在 src/layouts/basicLayout.jsx 定义一个布局组件,并在 .umirc.jsconfig/config.js 中配置:

javascript
export default {
  // 配置全局布局
  layout: {
    name: "BasicLayout",
    path: "@/layouts/basicLayout",
  },
};

动态路由与嵌套路由

对于更复杂的场景,比如需要处理嵌套路由或具有多个级别的动态参数,Umi 也提供了良好的支持。例如:

src/
├── pages/
│   ├── dashboard/
│   │   ├── index.jsx
│   │   └── settings/
│   │       └── [tab].jsx
│   └── products/
│       ├── index.jsx
│       └── [id].jsx

这会产生如下路由:

  • /dashboard 映射到 src/pages/dashboard/index.jsx
  • /dashboard/settings/:tab 映射到 src/pages/dashboard/settings/[tab].jsx
  • /products 映射到 src/pages/products/index.jsx
  • /products/:id 映射到 src/pages/products/[id].jsx

自定义路由配置

尽管 Umi 提供了强大的约定式路由功能,但在某些情况下,你可能仍然希望对路由进行一些自定义配置。这时可以通过 .umirc.jsconfig/config.js 文件来扩展或覆盖默认的路由设置。例如:

javascript
export default {
  routes: [
    { path: "/", component: "index" },
    { path: "/users", component: "users" },
    { path: "/users/:id", component: "users/[id]" },
    { path: "/about", component: "about" },
    // 添加更多自定义路由...
  ],
};

常见目录及其用途

1. pages 目录

pages 是存放页面组件的主要目录。Umi.js 会根据这个目录下的文件路径自动生成路由规则。每个 .jsx.tsx 文件代表一个独立的页面,并且文件路径直接映射到 URL 路径。

文件命名规则

  • 普通页面:例如 src/pages/home.jsx 对应 /home
  • 动态路由:使用方括号包裹参数名(如 [id])创建动态路由,用于匹配 URL 中的动态部分。例如 src/pages/users/[id].jsx 对应 /users/:id
  • 404 页面:创建名为 404.jsx 的文件作为未找到页面时的默认显示内容。
  • 重定向:可以通过 _redirects.jsx 文件定义重定向规则。

示例

假设你有如下文件结构:

src/
├── pages/
│   ├── home.jsx
│   ├── about.jsx
│   └── users/
│       ├── index.jsx
│       └── [id].jsx

这将自动生成以下路由表:

路径组件
/src/pages/home.jsx
/aboutsrc/pages/about.jsx
/userssrc/pages/users/index.jsx
/users/:idsrc/pages/users/[id].jsx

2. layouts 目录

layouts 目录用于存放布局组件,这些组件可以包裹其他页面组件,提供统一的布局样式或功能。通过这种方式,你可以为一组页面添加公共的头部、侧边栏、底部等元素,而无需在每个页面中重复编写相同的代码。

jsx
// src/pages/posts/_layout.js
import React from "react";
import { Layout, Menu } from "antd";
import Link from "umi";

const { Header, Sider, Content } = Layout;

export default function PostLayout({ children }) {
  return (
    <Layout>
      <Header>
        <Menu theme="dark" mode="horizontal" defaultSelectedKeys={["1"]}>
          <Menu.Item key="1">
            <Link to="/">Home</Link>
          </Menu.Item>
          <Menu.Item key="2">
            <Link to="/posts">Posts</Link>
          </Menu.Item>
        </Menu>
      </Header>
      <Layout>
        <Sider width={200} style={{ background: "#fff" }}>
          <Menu mode="inline" defaultSelectedKeys={["1"]}>
            <Menu.Item key="1">
              <Link to="/posts/new">New Post</Link>
            </Menu.Item>
            <Menu.Item key="2">
              <Link to="/posts/archive">Archive</Link>
            </Menu.Item>
          </Menu>
        </Sider>
        <Content style={{ padding: "0 24px", minHeight: 280 }}>
          {children}
        </Content>
      </Layout>
    </Layout>
  );
}

使用方法

要应用布局,可以在 .umirc.jsconfig/config.js 中进行全局配置:

javascript
export default {
  layout: {
    name: "BasicLayout",
    path: "@/layouts/basicLayout", // 指向布局组件的位置
  },
};

如果你只想为某些特定的页面应用布局,可以在路由配置中指定:

javascript
export default {
  routes: [
    { path: "/", component: "home" },
    {
      path: "/dashboard",
      layout: "@/layouts/dashboardLayout", // 为 /dashboard 及其子路由应用特定布局
      routes: [
        { path: "/dashboard/analytics", component: "dashboard/analytics" },
        { path: "/dashboard/settings", component: "dashboard/settings" },
      ],
    },
  ],
};

嵌套路由与布局

对于更复杂的场景,比如需要处理嵌套路由或具有多个级别的动态参数,layouts 目录可以帮助你更好地组织代码。例如:

src/
├── layouts/
│   ├── basicLayout.jsx
│   └── dashboardLayout.jsx
└── pages/
    ├── dashboard/
    │   ├── analytics.jsx
    │   └── settings.jsx

这样,你可以为不同部分的应用程序定义不同的布局,同时保持清晰的文件结构。

其他常用目录

除了 pageslayoutsUmi.js 还支持一些其他常见的目录,它们也有助于项目的组织:

3. models 目录

存放 Dva 模型文件的地方。每个模型负责管理特定业务逻辑的状态和副作用。通过集中管理和分层设计,可以使状态管理更加有序。

4. services 目录

用于存放服务端请求函数或其他异步操作逻辑。这有助于分离关注点,使代码更易于维护和测试。

5. components 目录

包含可复用的 UI 组件。通过将共享组件提取到这里,可以在多个页面之间轻松地重用它们,从而提高开发效率。

6. utils 目录

放置工具函数和其他辅助模块。这里可以包括日期格式化、字符串处理等通用功能,以减少重复代码。

总结

Umi.js 的约定式路由系统通过简单的文件夹和文件命名规范,实现了零配置的路由管理,大大减少了开发者的负担。同时,它也保留了一定程度上的灵活性,允许你在必要时进行自定义配置。这对于快速搭建应用原型、维护大型项目以及团队协作都非常有益。

Released under the MIT License.