- 在使用python的flask框架開發web應用時發現使用裝飾器控制路由真的很好用,這樣的寫法看起來比較直觀
@web.route('/register')
def register():
pass
@web.route('/login')
def login():
pass
@web.route('/save')
@auth
def save():
pass
下面來看下在nodejs里使用koa-decorator-router實現裝飾器路由
- 首先安裝
npm i koa koa-router koa-decorator-router
- 由于nodejs目前 還不支持裝飾器的寫法,所以需要配置babel,.babelrc配置如下,所以還需安裝
npm i babel-cli babel-core babel-plugin-transform-decorators-legacy babel-polyfill babel-preset-env babel-preset-stage-0 -D
{
"presets": ["env","stage-0"],
"plugins": ["transform-decorators-legacy"]
}
- 新建一個入口文件,引入項目的入口文件app.js
require('babel-core/register')()
require('babel-polyfill')
require('./server/app.js')
- app.js示例代碼如下
import Route, {
post,
put,
del,
get,
controller,
convert,
required
} from 'koa-decorator-router'
import Koa from 'koa'
import Router from 'koa-router'
import bodyParser from 'koa-bodyparser'
const app = new Koa()
const router = new Router()
const route = new Route()
app.use(bodyParser())
const middleware1 = convert(async (ctx, next) => {
console.log("middleware1")
await next()
})
@controller('/article')
class Article {
@get('/detail/:id')
@middleware1
getDetail(ctx) {
ctx.body = `detail ${ctx.params.id}`
}
@put('/add')
addArticle(ctx) {
ctx.body = 'add'
}
@post('/post')
@required({
body: ['id', 'name']
})
updateArticle(ctx) {
ctx.body = 'post'
}
@del('/del')
delArticle(ctx) {
ctx.body = 'del'
}
}
route.init(router)
app
.use(router.routes())
.use(router.allowedMethods())
app.listen(3000)
-
koa-decorator-router
里面包含了get、post、del、put、controller、 convert
方法和一個Route
類。- 其中
controller
是為了修飾類,接收一個參數url。所修飾的類下面的所有請求地址都應加上這個url。如上面代碼所示,請求地址就為/article/**
-
get、post、del、put
就是請求方式,為了修飾類下面的方法 -
convert
方法接收一個函數,將接收的函數轉化成中間鍵。當使用中間鍵是需要使用convert
方法轉化下,因為直接寫成裝飾器,因為它不知道裝飾器上方法是個中間鍵,如上面代碼所示middleware1
方法 -
required
這個方法支持一些簡單的參數校驗。它接收一個對象參數,里面的鍵可以為body
、params
和query
,鍵值是必傳參數組成的數組。如上面代碼所示,/post
接口的必傳參數是id
和name
。參數校驗只支持一級,需更復雜的校驗時,需要自己寫中間鍵進行校驗。
- 其中
- Route
-
init
接收一個參數,就是實例化的路由。這里需要注意是,在調用init
方法要放在所有聲明裝飾器類的后面執行,因為這步是將裝飾器路由上的所有方法掛載到路由上去 -
setRouterPath
設置導入路由文件夾的位置,并導入文件 -
setRouterPathAndInit
導入路由文件,完成后自動初始化
-
route.setRouterPathAndInit(path.resolve(__dirname, './routes'), router)
app
.use(router.routes())
.use(router.allowedMethods())
app.listen(3000)
or
async function start(){
await route.setRouterPath(path.resolve(__dirname, './routes'))
route.init(router)
app
.use(router.routes())
.use(router.allowedMethods())
app.listen(3000)
}
start()