这篇文章主要介绍一下umi约定式路由的使用。主要参考umi官方文档:https://umijs.org/zh-CN/docs/convention-routing
一、 基本使用
约定式路由是以文件系统为基础的路由。umi会分析src/pages目录,并根据目录文件结构自动生成对应的路由。如果你用过Jekyll或者Hugo之类的网页生成器,那就很容易理解约定式路由。
下面我们就来尝试一下。首先先看一下现在src/pages的目录结构(上一篇文章的脚手架创建的项目):
src
└── pages
├── index.less
└── index.tsx
我们来添加一个新的页面page1:
src
└── pages
├── index.less
└── index.tsx
└── page1.js
为了简便起见,这里使用了javascript,当然你也可以使用typescript。页面代码:
//page1.js
import React from 'react'
export default function Page1(props){
return(
<div>
This is page 1.
</div>
)
}
运行项目:
yarn start
打开浏览器 http://localhost:8000/page1 预览一下:
怎么是空白页面?因为umi约定只有当配置文件中没有routes这一项时才会启用约定式路由,所以我们还需要注释掉配置文件中的route配置:
//.umirc.ts
import { defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
// routes: [
// { path: '/', component: '@/pages/index' },
// ],
});
此时再预览一下,页面可以正常显示了。
当然,开发时为了更好的组织文件,我们会把有些非页面的文件或文件夹一起放到pages路径里。Umi提供了几种排除规则,满足以下规则的文件不会被注册为约定式路由:
- 以
.或_开头的文件或目录 - 以
d.ts结尾的类型定义文件 - 以
test.ts、spec.ts、e2e.ts结尾的测试文件(适用于.js、.jsx和.tsx文件) components和component目录utils和util目录- 不是
.js、.jsx、.ts或.tsx文件 - 文件内容不包含 JSX 元素
二、 动态路由
Umi约定以[]包裹的文件或文件夹为动态路由。我们直接来试一下,将刚刚创建的page1.js改成[page].js:
src
└── pages
├── index.less
└── index.tsx
└── [page].js
//[page].js
import React from 'react'
export default function Page(props){
return(
<div>
This is page {props.match.params.page}.
</div>
)
}
在组件中,我们可以通过props.match.params获取到动态url中的变量对象,然后通过相应的变量名获取变量值,这里的变量名就是page。
回到浏览器预览一下:http://localhost:8000/1024。可以任意修改url,页面会显示对应的参数。
注意:如果你发现路由失效了,或者没有更新,可以删除整个 src/.umi 目录,然后重新运行 yarn start。关于原因和.umi目录的作用,有时间会在之后的文章中探索一下。
三、 嵌套路由
Umi 里约定目录下有 _layout.tsx 时会生成嵌套路由。让我们再来更改一下页面:
src
└── pages
├── index.less
└── index.tsx
└── page1
└──_layout.js
└──child1.js
//_layout.js
import React from 'react'
export default (props)=>{
return(
<>
<h1>This is page layout.</h1>
{ props.children }
</>
)
}
//child1.js
import React from 'react';
export default (props)=>{
return(
<h2>This is child 1.</h2>
)
}
这样我们就可以通过localhost/page1和localhost/page1/child1来分别访问了。
注意page1路径下的所有文件都会携带_layout的布局。一般可以把页头,页脚,菜单等组件抽象出来放在_layout中。如果不想要共有的组件,那只需要把_layout里的多余元素清空即可:
//_layout.js
import React from 'react'
export default (props)=>{
return(
<>
{ props.children }
</>
)
}
四、 查看路由表
约定式路由不需要开发者手动编写路由配置,umi会自动分析目录并生成路由表。我们可以观察一下生成的路由文件:src\.umi\core\routes.ts
// @ts-nocheck
import React from 'react';
import { ApplyPluginsType } from 'C:***/node_modules/@umijs/runtime';
import * as umiExports from './umiExports';
import { plugin } from './plugin';
export function getRoutes() {
const routes = [
{
"path": "/",
"exact": true,
"component": require('@/pages/index.tsx').default
},
{
"path": "/page1",
"routes": [
{
"path": "/page1/child1",
"exact": true,
"component": require('@/pages/page1/child1.js').default
}
],
"component": require('@/pages/page1/_layout.js').default
}
];
// allow user to extend routes
plugin.applyPlugins({
key: 'patchRoutes',
type: ApplyPluginsType.event,
args: { routes },
});
return routes;
}
可以看到我们刚刚编写的嵌套路由其实就是在/page1下在嵌套一个routes属性。
五、 添加404页面
根据官方文档的说明,只需要在src\pages路径下添加404.tsx文件即可。我们来试一下:
src
└── pages
├── index.less
└── index.tsx
└── page1
└──_layout.js
└──child1.js
└── 404.tsx
//404.tsx
import React from 'react';
export default ()=>{
return(
<h1>404</h1>
)
}
然后随便输入一个url,比如http://localhost:8000/page1024。你会发现页面是空白。再试一下这个url,http://localhost:8000/404,可以显示404。
官方文档说404文件会被解析为:
{ component: '@/pages/404' }
并添加到路由表的末尾,我们可以查看一下routes.ts文件:
...
const routes = [
{
"path": "/404",
"exact": true,
"component": require('@/pages/404.tsx').default
},
{
"path": "/",
"exact": true,
"component": require('@/pages/index.tsx').default
},
{
"path": "/page1",
"routes": [
{
"path": "/page1/child1",
"exact": true,
"component": require('@/pages/page1/child1.js').default
}
],
"component": require('@/pages/page1/_layout.js').default
}
];
...
发现404并没有正确解析。那么我们手动修改一下route.ts文件呢?
...
const routes = [
{
"path": "/",
"exact": true,
"component": require('@/pages/index.tsx').default
},
{
"path": "/page1",
"routes": [
{
"path": "/page1/child1",
"exact": true,
"component": require('@/pages/page1/child1.js').default
}
],
"component": require('@/pages/page1/_layout.js').default
},
{
"component": require('@/pages/404.tsx').default
},
];
...
在打开http://localhost:8000/page1024。发现,这回成功了。
但是要注意的是,route.ts文件在开发中是会不断被重新构建的,所以不可以用这种方法解决问题。目前看来可能是一个小bug,我们需要持续关注umi的github issue看看官方后续有没有说明。
总结一下
Umi的约定式路由总的来说还是很方便的,但是3.x新版本貌似还不太为稳定,会有一些小的问题,比如添加404页面的问题。期望官方后期推出更新解决这些问题。接下来的文章将要介绍配置式路由的使用。