Node.js+Webpack开发实战
上QQ阅读APP看书,第一时间看更新

5.6 路由系统

路由是一个Web应用的核心功能,当然,Koa为了精简核心未包含路由功能,因此我们需要使用koa-router模块来实现路由功能。

5.6.1 快速开始

安装koa-router模块:

npm install koa-router –save

开始编码:

// 导入模块
const Koa = require('koa');
const Router = require('koa-router');
// 实例化应用
const app = new Koa();
// 实例化路由
const router = new Router();

// 路由定义
router.get('/', async (ctx) => {
   ctx.body = 'Hello World';
});
router.get('/user', async (ctx) => {
   ctx.body = 'User';
});

// 挂载路由中间件
app.use(router.routes());
app.use(router.allowedMethods());

// 监听
app.listen(10000, () => {
   console.log('listen on 10000');
});

访问http://localhost:10000,将输出“Hello World”;访问http://localhost:10000/user,将输出“User”。

一定不要忘记通过app.use()挂载路由中间件,否则路由将不会生效。

5.6.2 路由对象

路由需要实例化之后才能进行配置和挂载,路由的构造器函数签名如下:

function Router([options])

· options选项,一般使用的选项就是prefix。

 prefix:路由前缀。

实例化后的路由示例和Express类似,路由定义的方法如下:

router.method(path, handler);

· method:HTTP请求方法,支持get/post/put/delete/head/options。

· path:路由路径。

· handler:路由处理函数,支持多个。

5.6.3 路由路径

koa-router的路由路径支持字符串和字符串模式。

(1)以下是一些基于字符串的路由路径示例。

以下路由路径会将请求匹配到根路由/:

router.get('/', (ctx) => {
 ctx.body = 'Home';
});

以下路由路径会将请求匹配到/about:

router.get('/about', (ctx) => {
 ctx.body = '关于';
});

以下路由路径可以将请求匹配到/random.txt文件:

router.get('/random.txt', (ctx) => {
  ctx.body = 'random.txt';
});

(2)以下是一些基于字符串模式的示例。

以下路由路径可以匹配/users/xxx,匹配成功后xxx将挂载到ctx.params变量下:

5.6.4 路由函数

koa-router的路由函数和Koa默认的路由函数是相似的,也支持多个路由函数处理同一个请求。但是ctx.params只有koa-router的路由函数才可以访问。

5.6.5 路由级别中间件

Koa默认的中间件是应用级别的,所有的请求都会被中间件处理。由于koa-router也支持多个路由函数,因此可以在指定路由或者整个路由对象上使用中间件。

以下是整个路由对象启用中间件的示例。

// 日志中间件
async function logger(ctx, next) {
    console.log(`${ctx.method} ${ctx.path} ${ctx.headers['user-agent']}`);
    await next();
}
router.use(logger);
router.get('/', (ctx) => {
    ctx.body = 'home';
});
// 日志中间件
async function logger(ctx, next) {
    console.log(`${ctx.method} ${ctx.path} ${ctx.headers['user-agent']}`);
    await next();
}

router.get('/', logger, (ctx) => {
    ctx.body = 'home';
});

router.get('/user', (ctx) => {
    ctx.body = 'user';
});

5.6.6 路由前缀

路由前缀可以将同一个模块的路由聚合在一起,提供一个统一的URL前缀供客户端访问。

const Koa = require('koa');
const Router = require('koa-router');

const app = new Koa();
const router = new Router({ prefix: '/user' });

router.get('/', (ctx) => {
   ctx.body = '/user';
});

router.get('/list', (ctx) => {
   ctx.body = 'user/list';
});

app.use(router.routes()).use(router.allowedMethods());
// 监听
app.listen(10000, () => {
    console.log('listen on 10000');
});

上面的代码将提供以下路由以供访问:

/user 输出“/user”
/user/list 输出“/user/list”

5.6.7 模块化路由

为了保持项目的可维护性,建议将路由逻辑拆分到其他模块中,否则入口JS将越来越大,不利于代码维护。

Koa使用模块化路由的步骤非常简单:

· 独立文件中实现路由逻辑。

· 入口文件中挂载路由。

项目的目录结构如下:

// routes/site.js
const Router = require('koa-router');
const router = new Router();

router.get('/', (ctx) => {
    ctx.body = '首页';
});

router.get('/about', (ctx) => {
    ctx.body = '关于页';
});

module.exports = router;
// routes/user.js
const Router = require('koa-router');
const router = new Router({ prefix: '/user' });

router.get('/', (ctx) => {
    ctx.body = '用户首页';
});

router.get('/login', (ctx) => {
    ctx.body = '用户登录';
});

module.exports = router;
// koa.js
// 导入模块
const Koa = require('koa');
const app = new Koa();

// 导入路由模块
const siteRoute = require('./routes/site');
const userRouter = require('./routes/user');

// 挂载路由
app.use(siteRoute.routes()).use(siteRoute.allowedMethods());
app.use(userRouter.routes()).use(siteRoute.allowedMethods());
// 监听
app.listen(10000, () => {
   console.log('listen on 10000');
});

以上例子将生成以下路由:

/user
/user/login
/
/about