![Koa注解](https://cdn.portal.levenx.com/levenx-world/zGskWiREkWqGsGsA.jpg)
Koa注解
![乐闻的头像](https://cdn.portal.levenx.com/levenx-world/ghY0PdpLg5jTOhB9.jpg)
Koa注解
Node 支持装饰者模式
-
添加 babel 需要的 npm 包
javascriptyarn add @babel/core @babel/preset-env @babel/plugin-proposal-decorators @babel/polyfill @babel/register -D
-
新建 .babelrc 配置文件
javascript{ "presets": [ "@babel/preset-env" ], "plugins": [ [ "@babel/plugin-proposal-decorators", { "legacy": true } ] ] }
-
Node 前置执行 垫片代码
javascriptrequire('@babel/register')() require('@babel/polyfill') const app = new Koa(); app.use(async (ctx,next)=>{ ctx.body = { code:0 } }) const port = process.env.PORT || 3000; app.listen(port, () => { console.log(`app started on: ${port}`) })
此时 项目中可以使用装饰者注解@ 方式来操作了。
注解方式处理路由
- 添加
koa
相关依赖
javascriptyarn add glob koa koa-router
-
统一处理 koa 路由
javascriptconst path = require("path"); const Router = require("koa-router"); const glob = require("glob"); const symbolPrefix = Symbol('prefix'); //注解方法集合 const routerMap = new Map(); const isArray = obj => Array.isArray(obj) ? obj : [obj]; //注解方法集合 const methods = { POST: null, GET: null, PUT: null, DEL: null, ALL: null, OPTIONS: null, HEAD: null, PATCH: null }; //格式化路径 const formatPath = path => { path = path.url || path; return path === '/' ? '' : path.startsWith('/') ? path : `/${path}` } //注解方法汇总 const loadRouter = conf => (target, name, descriptor) => { conf.path = formatPath(conf.path); routerMap.set({ target, ...conf }, target[name]) //如果是 / 路径 if (conf.path === '/') { conf.path = ""; routerMap.set({ target, ...conf }, target[name]) } } //注解方法加载 Object.keys(methods).forEach((key) => { methods[key] = (path) => { return loadRouter({ method: key.toLowerCase(), path }) } }) //注解 Controller const Controller = (path) => { return target => { target.prototype[symbolPrefix] = path } } const Validate = (...mids) => { return (...args) => { const [target, name, descriptor] = args target[name] = isArray(target[name]) target[name].unshift(...mids) return descriptor } } class Route { constructor(app, apiPath) { this.app = app this.apiPath = apiPath this.router = new Router() } init() { // 将 api 文件接口全部同步载入 glob.sync(path.resolve(this.apiPath, './*.ts')).forEach(require) glob.sync(path.resolve(this.apiPath, './*.js')).forEach(require) for (let [conf, controller] of routerMap) { const controllers = isArray(controller) const prefixPath = conf.target[symbolPrefix] ? formatPath(conf.target[symbolPrefix]) : '' const routerPath = prefixPath + conf.path this.router[conf.method](routerPath, ...controllers) } this.app.use(this.router.routes()) this.app.use(this.router.allowedMethods()) } } // 解构所有的注解方法 const { POST, GET, PUT, DEL, ALL, OPTIONS, HEAD, PATCH } = methods; module.exports = { Controller, Route, POST, GET, PUT, DEL, ALL, OPTIONS, HEAD, PATCH, Validate }
-
项目使用decorator
javascriptrequire('@babel/register')() require('@babel/polyfill') const Koa = require("koa"); const path = require("path"); const { Route } = require('./utils/decorator'); const app = new Koa(); //路由处理 const apiPath = path.resolve(__dirname, './controller') new Route(app, apiPath).init(); const port = process.env.PORT || 3000; app.listen(port, () => { console.log(`app started on: ${port}`) })
-
路由注解使用
javascript// /src/controller/CommonController.js const { Controller, GET, POST, Validate } = require('../utils/decorator'); @Controller("/") export class CommonController { @GET("/") async home(ctx, next) { ctx.body = { message:"home" } } @GET('/test') async test(ctx, next) { ctx.body = { message:"测试" } } }