UmiJS 3.X实战从头开始(四):配置式路由与约定式路由

1. 配置式路由

在配置文件(.umirc.ts 或者 config/config.ts)中通过 routes 对象配置路由,就是配置式路由。如果没有 routes 配置项,则自动对 src/pages 目录生成约定式路由。

2. 约定式路由

约定式路由也叫文件路由,就是不需要手写配置,文件系统即路由,通过目录和文件及其命名分析出路由配置。

如果没有 routes 配置,Umi 会进入约定式路由模式,然后分析 src/pages 目录拿到路由配置。

需要注意的是,满足以下任意规则的文件不会被注册为路由,

  • ._ 开头的文件或目录
  • componentscomponent 目录
  • utilsutil 目录
  • 文件内容不包含 JSX 元素

1) 动态路由

约定 [] 包裹的文件或文件夹为动态路由。

比如:

  • src/pages/users/[id].tsx 会成为 /users/:id
  • src/pages/users/[id]/settings.tsx 会成为 /users/:id/settings

举个完整的例子,比如以下文件结构,

.
 └── pages
    └── [post]
       ├── index.tsx
       └── comments.tsx
    └── users
       └── [id].tsx
    └── index.tsx

会生成路由配置,

[
 { exact: true, path: '/', component: '@/pages/index' },
 { exact: true, path: '/users/:id', component: '@/pages/users/[id]' },
 { exact: true, path: '/:post/', component: '@/pages/[post]/index' },
 {
     exact: true,
     path: '/:post/comments',
     component: '@/pages/[post]/comments',
 },
];

动态路由会根据匹配到的动态参数生成 url,然后可以通过 props.match.params. 取到动态数据。例如在 src/pages/users/[id].tsx 中,通过 props.match.params.id 就可以获取到 id 的值。

2) 动态可选路由

约定 [ $] 包裹的文件或文件夹为动态可选路由。
例如:src/pages/users/[id$].tsx

动态可选路由和动态路由的区别,就在于动态路由如果没有动态参数,不会切换到路由对应的页面。而动态可选路由,没有动态参数也会展示默认页面内容。
例如当我们访问 /users/,如果是动态路由就看不到任何内容,而动态可选路由就可以看到相对应的页面默认内容。

3) 嵌套路由

Umi 里约定目录下有 _layout.tsx 时会生成嵌套路由,以 _layout.tsx 为该目录的 layout。layout 文件需要返回一个 React 组件,并通过 props.children 渲染子组件。

比如以下目录结构,

.
└── pages
 └── users
     ├── _layout.tsx
     ├── index.tsx
     └── list.tsx

会生成路由,

[
 { 
    exact: false, path: '/users', component: '@/pages/users/_layout',
    routes: [
        { exact: true, path: '/users', component: '@/pages/users/index' },
        { exact: true, path: '/users/list', component: '@/pages/users/list' },
    ]
 }
]

一个简单的 _layout.tsx 范例:

const layout: React.FC = (props) => {
  return (
    <>
      <div>user page</div>
      { props.children }
    </>
  );
};
export default layout;

4) 全局 layout

约定 src/layouts/index.tsx 为全局路由。同样,返回一个 React 组件,并通过 props.children 渲染子组件。

一个自定义的全局 layout 如下:

import ProLayout from '@ant-design/pro-layout';
import { IRouteComponentProps } from 'umi';

const Layout: React.FC<IRouteComponentProps> = (props) => {
  return (
    <ProLayout>
      <div>layout...</div>
      { props.children }
    </ProLayout>
  )
};
export default Layout;

5) 不同的全局 layout

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

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

import ProLayout from '@ant-design/pro-layout';
import { IRouteComponentProps } from 'umi';

const Layout: React.FC<IRouteComponentProps> = (props) => {
  if (props.location.pathname === '/login') {
    return <div>{ props.children }</div>
  }
  return (
    <ProLayout>
      <div>layout...</div>
      { props.children }
    </ProLayout>
  )
};
export default Layout;
需要注意的是,只是 约定式路由 不能设置多个全局layout文件,只能在 index.tsx 中对 location.path 做区分。如果是 配置式路由 的话,是完全可以给不同路由页面设置多个layout的(在路由配置文件里设置)。

5) 404 路由

约定 src/pages/404.tsx 为 404 页面,需返回 React 组件。

如果访问的路由和已按约定生成的路由都不能匹配,会 fallback 到 404 路由,通过 src/pages/404.tsx 进行渲染。

一个典型的 AntDesign 404路由页面:

import { Button, Result } from 'antd';
import React from 'react';
import { history } from 'umi';

const NoFoundPage: React.FC = () => (
  <Result
    status="404"
    title="404"
    subTitle="Sorry, the page you visited does not exist."
    extra={
      <Button type="primary" onClick={() => history.push('/')}>
        Back Home
      </Button>
    }
  />
);

export default NoFoundPage;

上一篇:UmiJS 3.X实战从头开始(三):配置与运行时配置
下一篇:UmiJS 3.X实战从头开始(五):插件


有为法
前端知识边学边写,为自己积累,也希望能为别人解惑。

一切有为法 如梦幻泡影

546 声望
24 粉丝
0 条评论
推荐阅读
Javascript高阶函数之理解与学习(一)
最近在学习和工作中用到了柯里化(curry),而柯里化是高阶函数(High-order Fucntion)的一种实现方式。为了更好的学习和理解D3js的编程方式,我们需要先把高阶函数的概念好好理清楚。

胡岗阅读 687

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木60阅读 5.9k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs39阅读 6.1k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木39阅读 7k评论 6

CSS 绘制一只思否猫
欢迎关注我的公众号:前端侦探练习 CSS 有一个比较有趣的方式,就是发挥想象,绘制各式各样的图案,比如来绘制一只思否猫?思否猫,SegmentFault 思否的吉祥物,是一只独一无二、特立独行、热爱自由的(&gt;^ω^&lt...

XboxYan41阅读 2.8k评论 14

封面图
还在用 JS 做节流吗?CSS 也可以防止按钮重复点击
举个例子:一个保存按钮,为了避免重复提交或者服务器考虑,往往需要对点击行为做一定的限制,比如只允许每300ms提交一次,这时候我想大部分同学都会到网上直接拷贝一段throttle函数,或者直接引用lodash工具库

XboxYan34阅读 2.2k评论 2

封面图
从零搭建 Node.js 企业级 Web 服务器(二):校验
校验就是对输入条件的约束,避免无效的输入引起异常。Web 系统的用户输入主要为编辑与提交各类表单,一方面校验要做在编辑表单字段与提交的时候,另一方面接收表单的接口也要做足校验行为,通过前后端共同控制输...

乌柏木32阅读 6k评论 9

一切有为法 如梦幻泡影

546 声望
24 粉丝
宣传栏