1. 程式人生 > 程式設計 >全棧專案|小書架|伺服器開發-Koa全域性路由實現

全棧專案|小書架|伺服器開發-Koa全域性路由實現

什麼是路由

路由就是具體的訪問路徑,指向特定的功能模組。一個api介面是由ip(域名)+埠號+路徑組成,例如 :https://www.npmjs.com/package/koa-router就是一個路由,指向了koa-routernpm頁面。

為什麼需要 koa-router 路由

當然不需要koa-router也能實現路由功能,通過ctx.request.path去指定路徑實現。例子如下:

const koa = require('koa2')
const app = new koa()

app.use(async (ctx,next) => {
    if (ctx.request.path === '/'
) { // 首頁 ctx.response.status = 200 ctx.response.body = 'index' } else if (ctx.request.path === '/list') { // 列表頁 ctx.response.status = 200 ctx.response.body = 'list' } else { ctx.throw(404,'Not found') // 404 } await next() }) app.listen(3000) 複製程式碼

參考:Koa 路由

以上程式碼只是實現兩個介面,就寫了不少程式碼,而寫是多層的判斷程式碼,可讀性已經很差了,這時候怎麼辦?

是不是可以將以上程式碼抽取出去,通過中介軟體的方式去實現。

結果是可以的,koa-router就是這樣做的。使用koa-router實現的例子如下:

  1. app.js 入口
  2. urls/home.js home 頁面的路由

app.js 的程式碼如下

// 路由模組使用前需要先安裝和例項化
const Router = require('koa-router')
const router = new Router()

// 首頁
app.use(async (ctx,next) => {
    if (ctx.request.path === '/') {
      ctx.response.status = 200
      ctx.response.body = 'index'
} await next() }) // 其他頁面通過 router 載入 let urls = fs.readdirSync(__dirname + '/urls') urls.forEach((element) => { let module = require(__dirname + '/urls/' + element) /* urls 下面的每個檔案負責一個特定的功能,分開管理 通過 fs.readdirSync 讀取 urls 目錄下的所有檔名,掛載到 router 上面 */ router.use('/' + element.replace('.js',''),module.routes(),module.allowedMethods()) }) app.use(router.routes()) 複製程式碼

urls/home.js 的程式碼如下

const Router = require('koa-router')
const home = new Router()

// /home
home.get('/',async (ctx,next) => {
    ctx.response.status = 200
    ctx.response.body = 'home'
    await next()
})

// home/list
home.get('/list',next) => {
    ctx.response.status = 200
    ctx.response.body = 'home-list'
    await next()
})

module.exports = home
複製程式碼

通過以上程式碼基本已經實現了全域性路由的功能了,剩下得就是在urls包下建立對應的檔案即可,參考home.js即可。

但是這裡的程式碼還是不夠完美,app.js作為入口檔案,這裡的程式碼還是有點多了;而且首頁和home的路由是分開來實現的。再而且urls路徑是固定的,後續資料夾名稱或者位置改變都會出現問題。

那麼如何實現呢? 這裡介紹一種思路:

  1. app.js中的程式碼抽取出來,讓app.js儘量簡單
  2. 將首頁和其他頁面都在全域性路由中實現

優雅的全域性路由實現

通過npm引入require-directory

require-directory npm包的作用是:

遞迴地遍歷指定目錄,對每個檔案進行require()

這裡也是利用了這個包去實現的。具體實現如下:

  1. core目錄下建立InitManager.js
const requireDirectory = require('require-directory')
const Router = require('koa-router')
/**
* 載入全域性路由
*/
static initLoadRouters(app){
   // 載入工作目錄下的 app/api 下的路徑
   const apiDirectory = `${process.cwd()}/app/api`
   
   // 引數:第一個引數固定引數module
   // 第二個引數要載入的模組的檔案路徑
   // 第三個引數:每次載入一個引數執行的函式
   requireDirectory(module,apiDirectory,{
       visit: whenLoadModule
   })
   
   function whenLoadModule(obj) {
       if(obj instanceof Router ){
           app.use(obj.routes())
       }
   }
}

module.exports = InitManager
複製程式碼

從上面的實現方式可以看出這裡使用了process.cwd()獲取路徑,而原有的程式碼中是通過__dirname去獲取路徑,那麼二者有什麼區別呢?

NodeJsprocess.cwd()__dirname的區別 process.cwd()是當前執行node命令時候的資料夾地址 ——工作目錄,保證了檔案在不同的目錄下執行時,路徑始終不變 __dirname 是被執行的js 檔案的地址 ——檔案所在目錄

  1. app.js中載入這個方法即可。
const app = new Koa()
InitManager.initLoadRouters(app)
複製程式碼
  1. app/api下建立相應的介面檔案即可,如home.js

諮詢請加微信:輕撩即可。

在這裡插入圖片描述