Table of Contents generated with DocToc
鉴于Koa的轻量级设计,其自身并没有提供route的功能,而需要我们自己去安装koa-router组件:
# 针对Koa2
$ npm install koa-router@next --save
// app/app.js
import Koa from 'koa';
import koaRouter from 'koa-router';
const app = new Koa();
const router = koaRouter();
router.get('/about', (ctx, next) => {
ctx.body = "this is the about page";
});
app
.use(router.routes())
.use(router.allowedMethods());
app.listen(7000);
export default app;
然后正常启动项目,进入localhost:7000/about
,就能看见也页面上加载的this is the about page
了。
koa-router
的更多使用方法,可以参考官方文档
当路由增多的时候,我们不可能把它们全部放在app.js
这个文件中,而是应该新建一个router.js
文件或者routes
文件夹。我更推荐使用文件夹的形式,那样的话,不同的路由可以根据各个文件来进行分类,更加便于管理:
- app
- routes
home.js
articles.js
# ...
index.js
编写home.js
:
// app/routes/home.js
import koaRouter from 'koa-router';
const router = koaRouter({
prefix: '/'
});
router.get('about', (ctx, next) => {
ctx.body = 'about page';
});
module.exports = router;
解释下prefix
:
路由的前缀。在这个文件里使用的router,在生成时带有参数{prefix: '/'}
,说明该文件里定义的路由都必须是以/
开头的,例如说/
,/about
,/articles
等。因为一个文件里只定义一个prefix
,所以便于之后进行管理。
而对于articles.js
:
// app/routes/articles.js
import koaRouter from 'koa-router';
const router = koaRouter({
prefix: '/articles'
});
// 路由/articles必须定义在含有{prefix: '/articles'}的路由文件里
router.get('/:id/author', (ctx, next) => {
ctx.body = 'article author page';
});
router.get('/:id/info', (ctx, next) => {
ctx.body = 'article info page';
});
// 要注意的是,需要把/路由,也就是/articles路由放在最后
// 因为路由是个中间件,会从上到下取第一个匹配的。
// 如果/articles在上面的话,则/:id/info会正常匹配,但/:id/info/会匹配到/articles
router.get('/', (ctx, next) => {
ctx.body = 'articles page';
});
module.exports = router;
上面文件里定义的路由有:
/articles
/articles/
/articles/:id/author
/articles/:id/info
此时进入localhost:7000/articles
页面,可以看见articles page
,并且进入类似localhost:7000/articles/1/author
这样的页面则也能获取到对应的article author page
最后,来看一下如何在index.js
便捷的获取到所有路由:
// app/routes/index.js
import fs from 'fs';
import path from 'path';
import koaRouter from 'koa-router';
const router = koaRouter();
fs
.readdirSync(__dirname)
.filter(file =>
(file.indexOf('.') !== 0) && (file.split('.').slice(-1)[0] === 'js') && file !== 'index.js'
)
.forEach(file => {
console.log(file);
const route = require(path.join(__dirname, file));
router.use(route.routes(), route.allowedMethods());
});
// 把根路由/放在最后,以免当其他路由后面带有/时匹配到根路由
router.get('/', (ctx, next) => {
ctx.body = 'home page';
});
export default router;
// 基本使用
import Koa from 'koa';
import koaRouter from 'koa-router';
const router = koaRouter();
const app = new Koa();
router.get('/', (ctx, next) => {
// ...
});
app
.use(router.routes())
.use(router.allowedMethods());
// 直接通过router.xxx方法即可,可以线性链接各方法
router
.get('/', (ctx, next) => {
ctx.body = 'Hello Koa';
})
.post('/users', (ctx, next) => {
// ...
})
.put('/users/:id', (ctx, next) => {
// ...
})
.del('/users/:id', (ctx, next) => {
// ...
});
router.get('/:category/:title', (ctx, next) => {
console.log(ctx.params);
});
// get: /programming/how-to-node
// -->
// log: { category: 'programming', title: 'how-to-node' }
router.get(
'/users/:id',
(ctx, next) => {
return User.findOne(ctx.params.id).then((user) => {
ctx.user = user;
return next();
});
},
(ctx) => {
console.log(ctx.user);
// => { id: 17, name: "Alex" }
}
);
const forums = new Router();
const posts = new Router();
posts.get('/', (ctx, next) => {...});
posts.get('/:pid', (ctx, next) => {...});
forums.use('/forums/:fid/posts', posts.routes(), posts.allowedMethods());
// 相当于posts接收的`/`和`/:pid`都嵌套到forums内
// 这样处理之后,app可以相应类似"/forums/123/posts"或者"/forums/123/posts/123"
app.use(forums.routes());
var router = new Router({
prefix: '/users'
});
router.get('/', ...); // responds to "/users"
router.get('/:id', ...); // responds to "/users/:id"