路由配置

icejs 推荐使用 配置式路由 进行应用的路由管理,如果希望使用文件约定路由可参考 文档

路由全局配置

src/app.ts 中,我们可以配置路由的类型和基础路径等信息,具体配置如下:

  1. import { runApp } from 'ice';
  2. const appConfig = {
  3. router: {
  4. type: 'browser',
  5. basename: '/seller',
  6. fallback: <div>loading...</div>
  7. modifyRoutes: (routes) => {
  8. return routes;
  9. }
  10. }
  11. };
  12. runApp(appConfig);

配置项说明:

  • type: 路由类型,默认值 hash,可选值 browser|hash|static
  • basename: 路由基准地址
  • fallback: 开启按需加载时配置 fallback UI
  • modifyRoutes: 动态修改路由
  • history: 自定义创建 history 对象,详见

路由列表配置

应用的路由信息统一在 src/routes.ts 中配置,配置协议支持多级嵌套,具体如下:

  1. import UserLayout from '@/Layouts/UserLayout';
  2. import UserLogin from '@/pages/UserLogin';
  3. import NotFound from '@/components/NotFound';
  4. import wrapperPage from '@/components/WrapperPage';
  5. const routerConfig = [
  6. // 分组路由,children 里的路由会将父节点的 component 作为布局组件
  7. {
  8. path: '/user',
  9. component: UserLayout,
  10. children: [
  11. {
  12. // 路由路径
  13. path: '/login',
  14. // 精确匹配
  15. exact: true,
  16. // 路由组件
  17. component: UserLogin,
  18. // 注意:仅 2.x 支持在 routes 中配置,icejs 1.x 只支持将 pageConfig 配置在对应的页面组件上,请参考「页面组件」章节
  19. pageConfig: {
  20. title: '登录页面',
  21. scrollToTop: true,
  22. // 自定义配置
  23. foo: 'bar',
  24. },
  25. },
  26. {
  27. path: '/',
  28. // 重定向
  29. redirect: '/user/login',
  30. },
  31. {
  32. // 404 没有匹配到的路由
  33. component: NotFound,
  34. },
  35. ],
  36. },
  37. // 非分组路由
  38. {
  39. path: '/about',
  40. component: About,
  41. },
  42. ];
  43. export default routerConfig;

注意:路由有一个按顺序匹配的规则,从上到下一旦命中路由匹配规则就会停止遍历,因此如果你在最前面配置了 / 这样一个路由,则所有的路由都会命中该规则,导致其他路由没有效果,所以在开发时要注意路由的顺序以及 exact: true 属性的使用。

路由跳转

通常使用 Link 组件或者 history API 进行路由的跳转:

  1. import { Link, useHistory } from 'ice';
  2. function Home() {
  3. const history = useHistory();
  4. return (
  5. <>
  6. <Link to="/about">去 about 页面</Link>
  7. <span
  8. onClick={() => {
  9. history.push('/about');
  10. }}
  11. >
  12. about 页面
  13. </span>
  14. </>
  15. );
  16. }

路由跳转传递参数,除了通过 url params 如 /projects/:id 以及 url query 如 /project?id=1 以外,也可通过 state 参数:

注意:state 传递参数仅支持 BrowserHistory 不支持 HashHistory,通过 src/app.ts 里的 router.type 字段可配置。

  1. import { Link, useHistory } from 'ice';
  2. function Home() {
  3. const history = useHistory();
  4. return (
  5. <>
  6. <Link
  7. to={{
  8. pathname: '/about',
  9. state: { from: 'click link' },
  10. }}
  11. >
  12. about 页面
  13. </Link>
  14. </>
  15. );
  16. }

在 about 页面即可通过 location 访问到对应的 state:

  1. import { useLocation } from 'ice';
  2. function About() {
  3. const location = useLocation();
  4. console.log('history state', location.state);
  5. return <></>;
  6. }

高阶指南

按需加载

参考 代码分割

HashHistory 与 BrowserHistory

前端路由通常有两种实现方式:HashHistory 和 BrowserHistory,路由都带着 # 说明使用的是 HashHistory。这两种方式优缺点:

特点\方案 HashHistory BrowserHistory
美观度 不好,有 # 号
易用性 简单 中等,需要 server 配合
依赖 server 端配置 不依赖 依赖
跟锚点功能冲突 冲突 不冲突
兼容性 IE8 IE10
state 传递参数 不支持 支持

开发者可以根据自己的实际情况选择对应方案。

如何使用 BrowserRouter

本地开发时,只需要在 src/app.ts 中增加以下配置即可:

  1. import { runApp } from 'ice';
  2. const appConfig = {
  3. router: {
  4. + type: 'browser',
  5. }
  6. };
  7. runApp(appConfig);

线上运行时需要服务端支持,否则会出现刷新 404 问题,具体方案请参考社区文档:

使用路由高阶组件

通过路由高阶组件可以对路由组件实现统一的业务逻辑(比如鉴权、埋点等)。

首先,实现一个高阶组件:

  1. // src/components/LoginWrapper
  2. import { useAuth, Redirect } from 'ice';
  3. const LoginWrapper = (WrappedComponent) => {
  4. const LoginWrappedPage = (props) => {
  5. const isLogin = true; // 替换成业务逻辑
  6. return <>{isLogin ? <WrappedComponent {...props} /> : <Redirect to="/login" />}</>;
  7. };
  8. return LoginWrappedPage;
  9. };
  10. export default LoginWrapper;

然后在 src/routes 中配置 wrappers 字段即可:

  1. +import WrapperPage from '@/components/WrapperPage';
  2. const routerConfig = [
  3. {
  4. path: '/user',
  5. component: User,
  6. + wrappers: [WrapperPage]
  7. },
  8. ]

注意:Wrapper 组件不支持通过 lazy 导入

动态路由参数

在某些场景下可能需要动态指定路由即 /user/:id,使用方式如下:

路由配置:

  1. import UserInfo from '@/pages/UserInfo';
  2. // src/routes.ts
  3. const routerConfig = [
  4. {
  5. path: '/user/:id',
  6. exact: true,
  7. component: UserInfo,
  8. },
  9. ];

动态路由参数:

  1. import { useParams } from 'ice';
  2. export default = () => {
  3. const { id } = useParams();
  4. // console.log(id) // 123
  5. }

如何配置带 . 的路由比如 /a.html

首先在 build.json 中开启配置项:

  1. {
  2. "devServer": {
  3. + "historyApiFallback": {
  4. + "disableDotRule": true
  5. + }
  6. }
  7. }

接着按照路由规则配置即可:

  1. // src/routes.ts
  2. import Home from '@/pages/Home';
  3. import About from '@/pages/About';
  4. export default [{
  5. path: '/home',
  6. component: Home,
  7. }, {
  8. + path: '/about.html',
  9. + exact: true,
  10. + component: About,
  11. }];