基於 Koa.js 的 Node.js MVC 框架

趙金添發表於2018-04-08

0. 簡介

  • 專案名:基於 Koa.js 的 Node.js MVC 框架。
  • 倉庫地址:github.com/zhaotoday/k…
  • 負責人:趙金添@zhaotoday
  • 特別說明:本專案參考了 Egg.js 框架及 iKcamp 分享的 Koa 視訊教程。

1. 執行

1.1. Node 版本

Koa2 使用了 async/await 等新語法,請保證 Node 版本在 7.6 及以上。

1.2. 命令

# 安裝依賴
$ npm install

# JS 程式碼校驗
$ npm run eslintfix
$ npm run eslint

# 開發
$ npm run dev

# 啟動專案
$ npm start

# 停止專案
$ npm run stop
複製程式碼

2. 規範

2.1. 目錄結構

├─ src                     原始碼
│  ├─ app                  業務程式碼
│  │  ├─ controllers       控制器:用於解析使用者輸入,處理後返回相應的結果
│  │  ├─ models            模型  :用於定義資料模型
│  │  ├─ services          服務  :用於編寫業務邏輯層,比如連線資料庫,呼叫第三方介面等
│  │  └─ views             檢視  :用於放置模板檔案,返回客戶端的檢視層
│  │
│  ├─ core                 核心程式碼
│  │  ├─ controller.js     控制器基類
│  │  ├─ model.js          模型基類
│  │  └─ service.js        服務基類
│  │
│  ├─ middlewares          中介軟體
│  ├─ public               靜態資源
│  ├─ router               URL 路由
│  ├─ utils                工具庫
│  └─ index.js             入口:用於自定義啟動時的初始化工作,比如啟動 https,呼叫中介軟體、路由等
│  
├─ .eslintrc               eslint 配置檔案
├─ nodemon.json            nodemon 配置檔案
├─ package.json            npm 配置檔案
├─ processes.json          pm2 配置檔案
複製程式碼

2.2. 自定義掛載物件

為了提高開發效率,這裡人為的將一些自定義物件掛載到 app 下,用 $ 字首命名,與 Koa.js 內建物件做區分。

  • app.$helpers:輔助函式
  • app.$model:公用模型物件
  • app.$Service:服務基類
  • app.$Controller:控制器基類
  • app.$models:模型集合
  • app.$services:服務集合
  • app.$controllers:控制器集合

2.3. 示例

2.3.1. 模型

src/app/models/articles.js

module.exports = app => {
  const {ID, SHORT_RELATED_ID, NAME, TITLE, SUBTITLE, DESCRIPTION, CONTENT, PICTURES, ORDER} = app.$model.columns

  return app.$model.define('articles', {
    id: ID,
    category_id: SHORT_RELATED_ID,
    author: NAME,
    title: TITLE,
    subtitle: SUBTITLE,
    description: DESCRIPTION,
    content: CONTENT,
    pictures: PICTURES,
    order: ORDER
  })
}
複製程式碼

2.3.2. 服務

src/app/services/articles.js

module.exports = app => {
  return class extends app.$Service {
    constructor () {
      super()

      this.model = app.$models.articles
    }
  }
}
複製程式碼

2.3.3. 控制器

src/app/controllers/articles.js

module.exports = app => {
  const service = app.$services.articles

  return class extends app.$Controller {
    async index (ctx, next) {
      await ctx.render('articles', {
        items: await service.find({offset: 0, limit: 10})
      })
    }
  }
}
複製程式碼

2.3.4. 檢視

src/app/views/articles.ejs

<%- JSON.stringify(items) %>
複製程式碼

2.3.5. API

src/app/controllers/apis/v1/articles.js

module.exports = app => {
  const service = app.$services.articles

  return class extends app.$Controller {
    async index (ctx, next) {
      ctx.response.body = ctx.send({
        status: 200,
        data: await service.find({offset: 0, limit: 10})
      })
    }
  }
}
複製程式碼

2.3.6. 路由

src/router/routes/articles.js

module.exports = (app, router) => {
  router.get('/articles', app.$controllers.articles.index)
}
複製程式碼

3. 參考

3.1. 文件

3.2. 文章

3.3. 安全

相關文章