說明
- 上一篇: [MVC實現之三]
- 上一篇實現了,Router層、Controller層、Service層的基本原則,并且成功的通過Mar類來傳遞這些層級之間需要的參數.
- 這一篇主要是通過業務層面來具體實現:
- Router層:監聽頁面的路由,并調用Controller層的路由處理函數
- Controller層:給Router層提供服務,調用Service層提供的數據處理.
開始
打開瀏覽器訪問: localhost:3000
- 此時并沒有,路由處理函數.
- 栗子: 返回一條數據
Router層
- 思路:
1.在該層調用koa-router
2.建立路由和路由處理函數的聯系
3.掛載路由
4.定義規則:將this.koa = new koa(conf)
改為this.$app = new koa(conf)
,使參數更具有語義(是一個koa的實例).
const koa = require('koa');
const koaRouter = require('koa-router');
class Mar {constructor(conf) {this.$app = new koa(conf);this.$router = new koaRouter();this.service = new Service(this);this.controller = new Controller(this);this.router = new Router(this);}
}class Router {constructor(app) {const { controller, $router, $app } = app;$router.get('/', controller.index);$app.use($router.routes());}
}
- 此時,Router層,成功的利用koa-router創建并掛載路由
- 下面只需在Controller類中寫入index方法.
- koa-router,在監聽路由的時候,會傳入一個ctx和next對象
Controller層
- 在此層寫入一個index方法,并使用ctx返回一個對象
class Controller {constructor() {const { service } = app;console.log('service:', service.test());this.service = service;}async index (ctx) {ctx.body = {name: 'marron',age: 18,remarks:`forever 18`}}
}
此時http://localhost:3000會返回如下信息:
- 調用Service層的異步方法
async index (ctx) {ctx.body = await service.getName();
}
- 重新刷新
http://localhost:3000
會報錯,原因是service沒有定義
- 仔細讀函數會發現:
- 我們僅僅只是在
constructor
函數中使用了this.service = service
this.service = service
實際上只是把方法掛載到(Controller)實例上.- 如何在類Controller的方法中使用Service層提供的方法呢?
-3.1 在JavaScript中實際上是沒有類的概念,類只不過是一個語法糖
-3.2 看以下代碼
class Point {constructor() {...},getX() {...},getY() {...}
}
// 等同于
Point.prototype = {constructor() {},getX() {},getY() {}
}
得益于以上,產生靈感如下:
- 在Controller層初始化的時候,將Service方法掛載到Controller的原型上
- 在內部方法使用時,先從原型上把需要的方法取出來
改進Router層
class Controller {constructor(app) {const { service } = app;console.log('service: ', service.test());// 將service掛載Controller的原型上Controller.prototype = service;}test() {return `Controller for Router`}async index(ctx) {const service = Controller.prototype.servicectx.body = await service.index();}
}
到這里,基本滿足了設計初衷:
- 通過Mar傳遞各層所需的參數
- 通過Router層監聽路由,并把路由對應到Controller層的方法
- Controller層調用Service層的方法
Service層
- 添加index層方法
class Service {constructor(app) {console.log('Service: ok');}test() {return `Service for Controller`}async index() {return {name: 'marron',age: 18,remarks: `forever 18`}}
}
總結
- 這一篇實現了Router、Controller、Service層內的具體通信
- 下一篇將會加入Model層.并對此系列進行總結