Skip to content
页面概要

路由

路由是组织起一个应用的关键骨架。

本项目路由分两部分:Vue前端路由Midway后端路由

触发机制

区分为以下两种情况

1、 当用户新打开页面或刷新页面:

Midway后端获取浏览器请求地址,对应到后端路由->经过viteServerRender处理->Vue前端路由接管,加载对应页面

2、当页面加载完成点击对应路由链接:

Vue前端路由直接接管,加载对应页面

Vue路由配置参数

TIP

本项目在原有的 vue-router 参数基础上扩展了如下参数:

import 'vue-router';
// 扩展 vue-router
declare module 'vue-router' {
  // 扩展meta字段
  interface RouteMeta {
    title?: string; // 标题
    keywords?: string; // 关键字
    description?: string; // 说明
    navActive?: string; // 选中的导航
  }
}

1
2
3
4
5
6
7
8
9
10
11
12

示例:







 
 
 
 








import { RouteRecordRaw } from 'vue-router';
const DefaultLayoutRoutes: Array<RouteRecordRaw> = [
    {
        path: '/detail',
        name: 'detail',
        meta: {
            title: '详情',
            keywords: '详情k',
            description: '详情d',
            navActive: 'about',
        },
        component: () =>
            import(/* webpackChunkName: "detail" */ '@/views/Detail/index.vue'),
    }
];

export default DefaultLayoutRoutes;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Seo 说明

title: seo标题,html的title标签内容

keywords: seo关键字,html的meta标签name="keywords"的内容

description: seo说明,html的meta标签name="description"的内容

高级用法请查看 seo 方法

INFO

navActive:用于设置选中的导航栏,需要在.vue模板中配合代码判断;此参数存在的原因,一般是因为详情页需要选中对应的导航,或其他特殊情况。



 
 
 




<template>
    <nav>
      <router-link to="/" :class="{'active': meta.navActive === 'home'}">Home</router-link> |
      <router-link to="/about" :class="{'active': meta.navActive === 'about'}">About</router-link> |
      <router-link :to="{path:'/localapi', query: {'uid':10}}" :class="{'active': meta.navActive === 'localapi'}">LocalApi</router-link>
    </nav>
    <router-view></router-view>
</template>
1
2
3
4
5
6
7
8

Vue路由

本项目设计了一个vue路由入口配置文件 /web/config/routes.ts,然后分别把路由拆分到了不同的/web/layouts中去配置,这样做的原因:一是在入口文件方便集中处理重新格式化;二是模块化更规范。

/web/config/routes.ts

/* 
 * # /web/config/routes.ts
 */
import {
  createRouter as _createRouter,
  createMemoryHistory,
  createWebHistory,
  Router,
} from 'vue-router';
import NProgress from 'nprogress'; // progress bar

import DefaultLayoutRoutes from '@/layouts/DefaultLayout/routes';
import DefaultLayout from '@/layouts/DefaultLayout/index.vue';

export const createRouter = (type: RouterType): Router => {
  const router = _createRouter({
    scrollBehavior(/* to, from, savedPosition */) {
      return { top: 0 };
    },
    history: type === 'web' ? createWebHistory() : createMemoryHistory(),
    routes: [
      {
        path: '/',
        name: 'root',
        component: DefaultLayout,
        children: DefaultLayoutRoutes,
      },
    ],
  });

  router.beforeEach((/* to, from */) => {
    if (!import.meta.env.SSR) {
      // start progress bar
      NProgress.start();
    }
  });

  router.afterEach(() => {
    if (!import.meta.env.SSR) {
      // finish progress bar
      NProgress.done();
    }
  });

  return router;
};
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

/web/layouts/DefaultLayout/routes.ts

/* 
 * # /web/layouts/DefaultLayout/routes.ts 
 */
import { RouteRecordRaw } from 'vue-router';
import Home from '@/views/Home/index.vue';

const DefaultLayoutRoutes: Array<RouteRecordRaw> = [
  {
    path: '/',
    name: 'home',
    meta: {
      title: '首页',
      keywords: '首页k',
      description: '首页d',
      navActive: 'home',
    },
    component: Home,
  },
  {
    path: '/about',
    name: 'about',
    meta: {
      title: '关于',
      keywords: '关于k',
      description: '关于d',
      navActive: 'about',
    },
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () =>
      import(/* webpackChunkName: "about" */ '@/views/About/index.vue'),
  },
  {
    path: '/detail',
    name: 'detail',
    meta: {
      title: '详情',
      keywords: '详情k',
      description: '详情d',
      navActive: 'about',
    },
    component: () =>
      import(/* webpackChunkName: "detail" */ '@/views/Detail/index.vue'),
  },
  {
    path: '/localapi',
    name: 'localapi',
    meta: {
      title: '请求本地api样列',
      keywords: '请求本地,api样列',
      description: '请求本地midway服务api样列',
      navActive: 'localapi',
    },
    component: () =>
      import(/* webpackChunkName: "about" */ '@/views/Localapi/index.vue'),
  },
];

export default DefaultLayoutRoutes;

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

Vue路由 详细规则请查看 官方文档

Midway路由

Midway 提供了这些装饰器: @Get 、 @Post 、 @Put() 、 @Del() 、 @Patch() 、 @Options() 、 @Head() 和 @All() ,表示各自的 HTTP 请求方法。

本项目Demo提供的样列在 /src/controller/home.controller.ts 中:

import { App, Inject, Controller, Get, ContentType } 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')
  @ContentType('text/html')
  async home(): Promise<void> {
    this.ctx.body = render(this.ctx, this.app);
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

@Get('/about') 、@Get('/detail') 、 @Get('/localapi') 可以用 @Get('/*')代替,这样后期就不用管这里了,只需要写前端路由就可以了,如下样例:















 







import { App, Inject, Controller, Get, ContentType } 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('/*')
  @ContentType('text/html')
  async home(): Promise<void> {
    this.ctx.body = render(this.ctx, this.app);
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Midway路由 详细规则请查看 官方文档

Released under the MIT License.