Umi 应用都是单页面应用,页面地址的跳转都是在浏览器端完成的,不会发起网络请求从服务器端获取 HTML。HTML 只在应用初始化时加载一次,后续路由的变化都是利用了浏览器的 API 实现。
所有的页面由不同的 React 组件构成,页面的切换其实是不同 React 组件的切换,只需要在配置中把不同的路由路径和对应的组件关联上。
提示: Umi 同时支持配置式路由和约定式路由。目前配置式路由是主流,本文主要介绍配置式路由。
配置路由
需要在配置文件中通过 routes 进行配置,它的格式是一个包含了路由信息的数组。
例如:
export default {
routes: [
{ exact: true, path: '/', component: 'index' },
{ exact: true, path: '/user', component: 'user' },
],
}
下面会分别解释其中的属性。
1.exact
类型是布尔值,表示是否严格匹配。例如
export default {
routes: [
// url 为 /one/two 时匹配失败
{ path: '/one', exact: true },
// url 为 /one/two 时匹配成功
{ path: '/one' },
{ path: '/one', exact: false },
],
}
2. path
类型是字符串,可以是被path-to-regexp@^1.7.0解析的路径通配符。
3. component
类型是字符串,配置和路由匹配后用于渲染的 React 组件的路径。
- 可以是绝对路径
- 可以是相对路径,从 src/pages 开始寻找
- 如果是 src 目录里的文件,可以用 @ ,也可以用 ../ 。例如 component: '@/layouts/basic' 和 component: '../layouts/basic' 是等同的,官方文档推荐使用前者。
4. routes
在 routes 内还可以嵌套 routes,这就是子路由功能,通常在需要为多个路径增加 layout 组件时使用。例如;
export default {
routes: [
{ path: '/login', component: 'login' },
{
path: '/',
component: '@/layouts/index',
routes: [
{ path: '/list', component: 'list' },
{ path: '/admin', component: 'admin' },
],
},
],
}
然后在 src/layouts/index 这个布局组件中通过 props.children 渲染子路由:
export default (props) => {
return <div style={{ padding: 20 }}>{ props.children }</div>;
}
这样,访问 /list 和 /admin 时就会使用 src/layouts/index 这个 layout 组件。
5. redirect
这个属性用于配置路由跳转,例如:
export default {
routes: [
{ exact: true, path: '/', redirect: '/list' },
{ exact: true, path: '/list', component: 'list' },
],
}
访问 / 就会跳转到 /list,并由 src/pages/list 文件进行渲染。
6. wrappers
它的属性值类型是数组,用于配置路由的高阶组件封装。
例如,可以用于路由级别的权限校验:
export default {
routes: [
{ path: '/user', component: 'user',
wrappers: [
'@/wrappers/auth',
],
},
{ path: '/login', component: 'login' },
]
}
然后在 src/wrappers/auth 中:
import { Redirect } from 'umi'
export default (props) => {
const { isLogin } = useAuth();
if (isLogin) {
return <div>{ props.children }</div>;
} else {
return <Redirect to="/login" />;
}
}
这样,访问 /user 就会调用 useAuth 函数做权限校验,如果通过就渲染 src/pages/user,否则跳转到 /login,由 src/pages/login 进行渲染。
7. title
这个属性值的类型是字符串。用于配置路由的标题。
页面跳转
Umi 推荐的页面跳转方式是使用其内部提供的 history 接口,用法如下:
import { history } from 'umi';
// 跳转到指定路由
history.push('/list');
// 带参数跳转到指定路由
history.push('/list?a=b');
history.push({
pathname: '/list',
query: {
a: 'b',
},
});
// 跳转到上一个路由
history.goBack();
在底层 Umi 采用的是 ReactTraining/history,它支持 3 种不同类型的 history,取决于你的运行环境和项目需求:
- browser history - 适用于支持 HTML5 history API 的现代浏览器
- hash history - 适用于旧版浏览器,或者你想把 location 保存到 hash 部分,避免由于后端服务器不支持而报错
- memory history - 把 history 保存在内存里,适合非浏览器环境,如 React Native 或测试时
在 Umi 中默认是采用 browser history。
hash 路由
如果你想采用 hash 路由,即上面提到的 hash history,需要在配置文件手动指定:
export default {
history: {
type: 'hash'
}
}
单页面内部跳转
单页面内部的跳转可以用 Umi 提供的 Link 组件,例如:
import { Link } from 'umi';
export default () => (
<div>
<Link to="/users">Users Page</Link>
</div>
);
点击 Users Page 就会跳转到 /users 地址。
注意:Link 组件只适用于单页面内部跳转,跳转到外链需要用 a 标签。
在组件中访问路由信息
在组件中可以通过 props 获取到路由相关的信息:
- match - 当前路由和 url match 后的对象,包含 params, path, url 和 isExact 属性
- location - 表示应用当前处于哪个位置,包含 pathname, search, query 等属性
- history - history 对象
- route - 当前路由配置,包含 path, exact, component, routes 等
- routes - 已配置的全部路由信息
用法示例:
export default function(props) {
console.log(props.route);
return <div>Home Page</div>;
}