路由
路由是组织起一个应用的关键骨架。
本项目路由分两部分:React前端路由
和 Midway后端路由
。
触发机制
区分为以下两种情况
1、 当用户新打开页面或刷新页面:
Midway后端获取浏览器请求地址,对应到后端路由
->经过viteServerRender处理
->React前端路由接管,加载对应页面
2、当页面加载完成点击对应路由链接:
React前端路由直接接管,加载对应页面
React路由配置参数
TIP
本项目定义了路由参数如下:
ts
/**
* meta 自定义
*/
export interface IRouteMeta {
// 标题,路由在菜单、浏览器title 或 面包屑中展示的文字
title?: string;
keywords?: string; // 关键字
description?: string; // 说明
navActive?: string; // 选中的导航
parentPath?: string[]; // 所有父元素的path,下标key按照父元素的顺序
}
export type RouteComponent = React.FC<BrowserRouterProps> | (() => any);
/**
* 路由类型
*/
export interface IRouter {
path: string;
meta?: IRouteMeta;
redirect?: string;
component?: RouteComponent;
children?: IRouter[];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
示例:
ts
import { lazy } from 'react';
import { IRouter } from '@/@types/router';
const LayoutRoutes: IRouter[] = [
{
path: '/',
meta: {
title: '首页',
keywords: '首页k',
description: '首页d',
navActive: 'home',
},
component: lazy(() => import('@/pages/Home')),
},
];
export default LayoutRoutes;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Seo 说明
title
: seo标题,html的title标签内容
keywords
: seo关键字,html的meta标签name="keywords"的内容
description
: seo说明,html的meta标签name="description"的内容
高级用法请查看 seo 方法。
INFO
navActive
:用于设置选中的导航栏,需要在.tsx
模板中配合代码判断;此参数存在的原因,一般是因为详情页需要选中对应的导航,或其他特殊情况。
tsx
import { memo } from 'react';
import { Link } from 'react-router-dom';
import classnames from 'classnames';
import { useAsyncDataMetaContext } from '@/store/asyncDataContext';
import './css/index.less';
export interface DefaultLayoutProps {
children: React.ReactNode;
}
export default memo(({ children }: DefaultLayoutProps) => {
const meta = useAsyncDataMetaContext();
return (
<>
<nav>
<Link
to={'/'}
className={classnames({ active: meta.navActive === 'home' })}
>
Home
</Link>
|
<Link
to={'/about'}
className={classnames({ active: meta.navActive === 'about' })}
>
About
</Link>
|
<Link
to={{ pathname: '/localapi', search: 'uid=10' }}
className={classnames({ active: meta.navActive === 'localapi' })}
>
LocalApi
</Link>
</nav>
{children}
</>
);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
React路由
本项目设计了一个react路由入口配置文件 /web/config/routes.tsx
,然后分别把路由拆分到了不同的/web/layouts
中去配置,这样做的原因:一是在入口文件方便集中处理重新格式化;二是模块化更规范。
/web/config/routes.tsx
ts
/*
* # /web/config/routes.tsx
*/
/**
* 路由配置 入口
* @author LiQingSong
*/
import { lazy, memo, Suspense } from 'react';
import { useLocation, useRoutes } from 'react-router-dom';
import { createUseRoutes, pathKeyCreateUseRoutes } from '@/utils/router';
import PageLoading from '@/components/PageLoading';
// BlankLayout
import BlankLayout from '@/layouts/BlankLayout';
// DefaultLayout
import DefaultLayoutRoutes from '@/layouts/DefaultLayout/routes';
import DefaultLayout from '@/layouts/DefaultLayout';
import { IRouter } from '@/@types/router';
/**
* 配置所有路由
*/
export const originalRoutes: IRouter[] = [
{
path: '/',
children: DefaultLayoutRoutes,
},
];
/**
* 配置的路由转RouteObject[]
*/
export const routes = createUseRoutes([
...originalRoutes,
{
path: '*',
component: lazy(() => import('@/pages/404')),
},
]);
/**
* 配置框架对应的路由
*/
const layoutToRoutes = {
DefaultLayout: pathKeyCreateUseRoutes([routes[0]]),
};
export const SuspenseLazy = memo(
({ children }: { children: React.ReactNode }) => (
<Suspense fallback={<PageLoading />}>{children}</Suspense>
)
);
export default memo(() => {
const routesElement = useRoutes(routes);
const location = useLocation();
// 属于 DefaultLayout
if (layoutToRoutes.DefaultLayout[location.pathname]) {
return (
<DefaultLayout>
<SuspenseLazy>{routesElement}</SuspenseLazy>
</DefaultLayout>
);
}
// 默认 BlankLayout
return (
<BlankLayout>
<SuspenseLazy>{routesElement}</SuspenseLazy>
</BlankLayout>
);
});
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/web/layouts/DefaultLayout/routes.ts
ts
/*
* # /web/layouts/DefaultLayout/routes.ts
*/
import { lazy } from 'react';
import { IRouter } from '@/@types/router';
// import About from '@/pages/About';
const LayoutRoutes: IRouter[] = [
{
path: '/',
meta: {
title: '首页',
keywords: '首页k',
description: '首页d',
navActive: 'home',
},
component: lazy(() => import('@/pages/Home')),
},
{
path: '/about',
meta: {
title: '关于',
keywords: '关于k',
description: '关于d',
navActive: 'about',
},
//component: About,
component: lazy(() => import('@/pages/About')),
},
{
path: '/detail',
meta: {
title: '详情',
keywords: '详情k',
description: '详情d',
navActive: 'about',
},
component: lazy(() => import('@/pages/Detail')),
},
{
path: '/localapi',
meta: {
title: '请求本地api样列',
keywords: '请求本地,api样列',
description: '请求本地midway服务api样列',
navActive: 'localapi',
},
component: lazy(() => import('@/pages/Localapi')),
},
];
export default LayoutRoutes;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
React路由
详细规则请查看 官方文档。
Midway路由
Midway 提供了这些装饰器: @Get 、 @Post 、 @Put() 、 @Del() 、 @Patch() 、 @Options() 、 @Head() 和 @All() ,表示各自的 HTTP 请求方法。
本项目Demo提供的样列在 /src/controller/home.controller.ts
中:
ts
import { App, Controller, Get, Inject } from '@midwayjs/decorator';
import { Application, Context } from '@midwayjs/koa';
import { render } from '../vite.server';
@Controller('/')
export class HomeController {
@App()
app: Application;
@Inject()
ctx: Context;
@Get('/')
@Get('/about')
@Get('/detail')
@Get('/localapi')
@Get('/404')
async home(): Promise<void> {
render(this.ctx, this.app, true);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Midway路由
详细规则请查看 官方文档。