# 路由
路由的概念来源于服务端,在服务端中路由描述的是URL与处理函数之间的对应关系。
路由是引导、匹配之意,于描述 URL 与处理函数之间的对应关系的。根据URL变更重新渲染页面布局和内容的过程。 传统路由整个界面切换,白屏等多个问题,体验不好。而前端路由则以SPA为准则,体验更佳:在页面不刷新的前提下实现URL变化且能捕捉到变化做出相应的逻辑。
const{url,path,method}=ctx ;
console.log(url===path)//true
put delete get post all等,all()一般用于设置请求头,如设置过期时间,CORS
router.all('/*',async(ctx,next)=>{
ctx.set('Access-Control-Allow-Origin',''https://xxxx/xx)
})
# 命名路由
使用router.url()方法可以在代码中根据路由名称和参数(可选)生成具体URL
//设置了路由名称为user
router.get('user', '/users/:id', function (ctx, next) {
// ...
});
router.url('user', 3);
// => 生成路由 "/users/3"
router.url('user', { id: 3 });
// => 生成路由 "/users/3"
router.use(function (ctx, next) {
// 重定向到路由名称为 “sign-in” 的页面
ctx.redirect(ctx.router.url('sign-in'));
})
# 多中间件
可把一个路由拆分,更佳容易维护
const koa = require('koa')
const compose=require('koa-compose')
const bodyParser=require('koa-bodyparser')
const Router=require('koa-router')
const app = new koa()
const router= new Router()
router.get('/100',(ctx,next)=>{
ctx.body='1000'
next()
},(ctx,next)=>{
console.log(1000)
})
app
.use(bodyParser())
.use(router.routes())
.use(router.allowedMethods())
app.listen(3000,()=>{
console.log("ok")
})
//localhost://3000/100
//界面1000,控制台也输出1000
# 嵌套路由
可以在应用中定义多个路由,然后把这些路由组合起来用,这样便于管理多个路由,也简化了路由的写法。
var forums = new Router();
var posts = new Router();
posts.get('/', function (ctx, next) {...});
posts.get('/:pid', function (ctx, next) {...});
forums.use('/forums/:fid/posts', posts.routes(), posts.allowedMethods());
// 可以匹配到的路由为 "/forums/123/posts" 或者 "/forums/123/posts/123"
app.use(forums.routes());
router.use()
# 路由前缀
通过 prefix 这个参数,我们可以为一组路由添加统一的前缀,和嵌套路由类似,也方便我们管理路由和简化路由的写法。不同的是,前缀是一个固定的字符串,不能添加动态参数。
var router = new Router({
prefix: '/users'
});
router.get('/', ...); // 匹配路由 "/users"
router.get('/:id', ...); // 匹配路由 "/users/:id"
# URL参数
koa-router 也支持参数,参数会被添加到 ctx.params 中。参数可以是一个正则表达式,这个功能的实现是通过 path-to-regexp 来实现的。原理是把 URL 字符串转化成正则对象,然后再进行正则匹配,之前的例子中的 * 通配符就是一种正则表达式。
router.get('/:category/:title', function (ctx, next) {
console.log(ctx.params);
// => { category: 'programming', title: 'how-to-node' }
});
通过上面的例子可以看出,可以通过 ctx.params 去访问路由中的参数,使得能对参数做一些处理后再执行后续的代码。
# 接口权限设置
cookie认证和token认证
jsonwebtoken(JWT)
cnpm install --save jwt-simple
cnpm i koa-body -S
cnpm i --save koa-jwt
const Koa = require('koa')
const Router = require('koa-router')
const jwt = require('jwt-simple')
const koaBody = require('koa-body')
const koaJwt = require('koa-jwt') //路由权限控制
const app = new Koa()
const router = new Router()
//秘钥
const jwtSecret = 'jwtSecret'
const tokenExpiresTime = 1000 * 60 * 60 * 24 * 7
// Custom 401 handling if you don't want to expose koa-jwt errors to users
app.use(function(ctx, next){
return next().catch((err) => {
if (401 == err.status) {
ctx.status = 401;
ctx.body = 'Protected resource, use Authorization header to get access\n';
} else {
throw err;
}
});
});
app.use(koaJwt({secret:jwtSecret}).unless({
path:[/^\/login/]
}))
router.get('/', (ctx) => {
ctx.body = 'Hello koa-jwt'
})
// router.use(koaJwt(jwtSecret).unless({
// path:[/^\/login/]
// }))
router.post('/login', koaBody(), (ctx) => {
const user = ctx.request.body
if (user && user.name){
let payload = {
exp:Date.now() + tokenExpiresTime,
name:user.name
}
let token = jwt.encode(payload, jwtSecret)
ctx.body = {
user:user.name,
code:1,
token
}
}else {
ctx.body = {
code:-1
}
}
})
// router.use(koaJwt(jwtSecret))
router.get('/userInfo', ctx => {
let token = ctx.header.authorization
ctx.body = {
token:token,
user:ctx.state.user
}
//使用jwt-simple自行解析数据
let payload = jwt.decode(token.split(' ')[1], jwtSecret);
console.log(payload)
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(3000, () => {
console.log('app listening 3000...')
})
// curl -d 'name=lili&password=20' http://localhost:3000/login
/* {
"user":"lili",
"code":1,
"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NTgwNjgx
NTYwNjYsIm5hbWUiOiJsaWxpIn0.ty1fzvwDcDJhmYjUbbgo36aSCvIREFJ6FKvcSqmsefU"}*/
# 前端路由的概念
- 前端路由分为hash路由,通过hashchange时间捕获hash变化。
- history路由,通过popstate时间捕获url变化。
- 内存路由:该方案一般适用于非浏览器环境如RN/测试等