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