说明
- 上一篇: [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层.并对此系列进行总结