koa --- > [MVC实现之四]Router、Controller、Service的实现

说明

  • 上一篇: [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没有定义
  • 仔细读函数会发现:
  1. 我们仅仅只是在constructor函数中使用了this.service = service
  2. this.service = service实际上只是把方法挂载到(Controller)实例上.
  3. 如何在类Controller的方法中使用Service层提供的方法呢?
    -3.1 在JavaScript中实际上是没有类的概念,类只不过是一个语法糖
    -3.2 看以下代码
class Point {
	constructor() {...},
   	getX() {...},
   	getY() {...}
}
// 等同于
Point.prototype = {
	constructor() {},
	getX() {},
	getY() {}
}

得益于以上,产生灵感如下:

  1. 在Controller层初始化的时候,将Service方法挂载到Controller的原型上
  2. 在内部方法使用时,先从原型上把需要的方法取出来

改进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.service
		ctx.body = await service.index();
	}
}

到这里,基本满足了设计初衷:

  1. 通过Mar传递各层所需的参数
  2. 通过Router层监听路由,并把路由对应到Controller层的方法
  3. 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层.并对此系列进行总结
发布了177 篇原创文章 · 获赞 22 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/piano9425/article/details/103418832
koa