亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

你可能會用到的一個路由適配器

標簽:
Node.js

前言

此时状态有点像上学时写作文,开篇总是"拉"不出来,憋的难受。

原文地址

源码地址

憋的难受

从背景出发

前后端分离后,前端童鞋会需要处理一些node层的工作,比如模板渲染、接口转发、部分业务逻辑等,比较常用的框架有koa、koa-router等。

现在我们需要实现这样一个需求:

  1. 用户访问/fe的时候,页面展示hello fe

  2. 用户访问/backend的时候,页面展示hello backend

你是不是在想,这需求俺根本不用koakoa-router,原生的node模块就可以搞定。

const http = require('http') const url = require('url') const PORT = 3000 http.createServer((req, res) => {   let { pathname } = url.parse(req.url)   let str = 'hello'   if (pathname === '/fe') {     str += ' fe'   } else if (pathname === '/backend') {     str += ' backend'   }   res.end(str) }).listen(PORT, () => {   console.log(`app start at: ${PORT}`) })

确实是,对于很简单的需求,用上框架似乎有点浪费,但是对于以上的实现,也有缺点存在,比如

  1. 需要我们自己去解析路径。

  2. 路径的解析和逻辑的书写耦合在一块。如果未来有更多更复杂的需求需要实现,那就gg了。

所以接下来我们来试试用koakoa-router怎么实现

app.js

const Koa = require('koa') const KoaRouter = require('koa-router') const app = new Koa() const router = new KoaRouter() const PORT = 3000 router.get('/fe', (ctx) => {   ctx.body = 'hello fe' }) router.get('/backend', (ctx) => {   ctx.body = 'hello backend' }) app.use(router.routes()) app.use(router.allowedMethods()) app.listen(PORT, () => {   console.log(`app start at: ${PORT}`) })

通过上面的处理,路径的解析倒是给koa-router处理了,但是整体的写法还是有些问题。

  1. 匿名函数的写法没有办法复用

  2. 路由配置和逻辑处理在一个文件中,没有分离,项目一大起来,同样是件麻烦事。

接下来我们再优化一下,先看一下整体的目录结构

├──app.js // 应用入口 ├──controller // 逻辑处理,分模块 │   ├──hello.js │   ├──aaaaa.js ├──middleware // 中间件统一注册 │   ├──index.js ├──routes // 路由配置,可以分模块配置 │   ├──index.js ├──views // 模板配置,分页面或模块处理,在这个例子中用不上 │   ├──index.html

预览一下每个文件的逻辑

app.js 应用的路口

const Koa = require('koa') const middleware = require('./middleware') const app = new Koa() const PORT = 3000 middleware(app) app.listen(PORT, () => {   console.log(`app start at: ${PORT}`) })

routes/index.js 路由配置中心

const KoaRouter = require('koa-router') const router = new KoaRouter() const koaCompose = require('koa-compose') const hello = require('../controller/hello') module.exports = () => {   router.get('/fe', hello.fe)   router.get('/backend', hello.backend)   return koaCompose([ router.routes(), router.allowedMethods() ]) }

controller/hello.js hello 模块的逻辑

module.exports = {   fe (ctx) {     ctx.body = 'hello fe'   },   backend (ctx) {     ctx.body = 'hello backend'   } }

middleware/index.js 中间件统一注册

const routes = require('../routes') module.exports = (app) => {   app.use(routes()) }

写到这里你可能心里有个疑问?

一个简单的需求,被这么一搞看起来复杂了太多,有必要这样么?

答案是:有必要,这样的目录结构或许不是最合理的,但是路由、控制器、view层等各司其职,各在其位。对于以后的扩展有很大的帮助。

不知道大家有没有注意到路由配置这个地方

routes/index.js 路由配置中心

const KoaRouter = require('koa-router') const router = new KoaRouter() const koaCompose = require('koa-compose') const hello = require('../controller/hello') module.exports = () => {   router.get('/fe', hello.fe)   router.get('/backend', hello.backend)   return koaCompose([ router.routes(), router.allowedMethods() ]) }

每个路由对应一个控制器去处理,很分离,很常见啊!!!这似乎也是我们平时在前端写vue-router或者react-router的常见配置模式。

但是当模块多起来的来时候,这个文件夹就会变成

const KoaRouter = require('koa-router') const router = new KoaRouter() const koaCompose = require('koa-compose') // 下面你需要require各个模块的文件进来 const hello = require('../controller/hello') const a = require('../controller/a') const c = require('../controller/c') module.exports = () => {   router.get('/fe', hello.fe)   router.get('/backend', hello.backend)   // 配置各个模块的路由以及控制器   router.get('/a/a', a.a)   router.post('/a/b', a.b)   router.get('/a/c', a.c)   router.get('/a/d', a.d)   router.get('/c/a', c.c)   router.post('/c/b', c.b)   router.get('/c/c', c.c)   router.get('/c/d', c.d)   // ... 等等       return koaCompose([ router.routes(), router.allowedMethods() ]) }

有没有什么办法,可以让我们不用手动引入一个个控制器,再手动的调用koa-router的get post等方法去注册呢?

比如我们只需要做以下配置,就可以完成上面手动配置的功能。

routes/a.js

module.exports = [   {     path: '/a/a',     controller: 'a.a'   },   {     path: '/a/b',     methods: 'post',     controller: 'a.b'   },   {     path: '/a/c',     controller: 'a.c'   },   {     path: '/a/d',     controller: 'a.d'   } ]

routes/c.js

module.exports = [   {     path: '/c/a',     controller: 'c.a'   },   {     path: '/c/b',     methods: 'post',     controller: 'c.b'   },   {     path: '/c/c',     controller: 'c.c'   },   {     path: '/c/d',     controller: 'c.d'   } ]

然后使用pure-koa-router这个模块进行简单的配置就ok了

const pureKoaRouter = require('pure-koa-router') const routes = path.join(__dirname, '../routes') // 指定路由 const controllerDir = path.join(__dirname, '../controller') // 指定控制器的根目录 app.use(pureKoaRouter({   routes,   controllerDir }))

这样整个过程我们的关注点都放在路由配置上去,再也不用去手动require一堆的文件了。

简单介绍一下上面的配置

{   path: '/c/b',   methods: 'post',   controller: 'c.b' }

path: 路径配置,可以是字符串/c/b,也可以是数组[ '/c/b' ],当然也可以是正则表达式/\c\b/

methods: 指定请求的类型,可以是字符串get或者数组[ 'get', 'post' ],默认是get方法,

controller: 匹配到路由的逻辑处理方法,c.b 表示controllerDir目录下的c文件导出的b方法,a.b.c表示controllerDir目录下的/a/b 路径下的b文件导出的c方法

源码实现

接下来我们逐步分析一下实现逻辑

pure-koa-router接收

  1. routes

    1. 可以指定具体的文件,这样pure-koa-router读取指定的文件内容作为路由配置 const routes = path.join(__dirname, '../routes/tasks.js')

    2. 可以直接指定文件导出的内容 (const routes = require('../routes/index'))

    1. 可以指定路由的文件目录,这样pure-koa-router会去读取该目录下所有的文件 (const routes = path.join(__dirname, '../routes'))

  2. controllerDir、控制器的根目录

  3. routerOptions new KoaRouter时候传入的参数,具体可以看

    源码的实现过程基本就到这里了。

    结尾

    pure-koa-router将路由配置和控制器分离开来,使我们将注意力放在路由配置和控制器的实现上。希望对您能有一点点帮助。

    原文地址

    源码地址


點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消