koa --- > [MVC实现之二]Controller层的实现

[MVC实现之一]传送门

https://blog.csdn.net/piano9425/article/details/103362966

Router层

  • router这一层,不做业务处理,仅仅只是将路由和路由的处理函数结合起来.
  • 路由的处理函数由Controller层实现
  • 改进目录结构如下(实际上新建了controller文件夹及其内部子文件,mar.js)
    在这里插入图片描述

Router层的改变

  • 我们希望routes下的index.js结构如下
    "get /": indexHandler;
    "get /detail: detailHandler"
  • 改成如下:
module.exports = app => ({
	'get /': app.controller.home.index,
	'get /detail': app.controller.home.detail
})

注:
1.此时导出的是一个函数,而不是一个对象
2.现在已经有了路由,以及路由的处理函数的名称.
3.路由的逻辑将在Controller层内完成

Controller实现路由逻辑

  • /mar/controller/home.js
module.exports = ctx => {
	index: async ctx =>{
		ctx.body = 'Controller Index'
	},
	detail: async ctx =>{
		ctx.body = 'Controller detail'
	}
}

注:
1.实现的逻辑很简单:根据请求的URL返回内容给浏览器渲染
2.现在有了,路由,路由的处理函数,路由与路由处理函数的对应.
3.下面只需将controller文件夹下的函数挂载到app上即可.
4.app是函数的实例

构造mar类

思路:
1.希望通过如下方式启动

// mar/index.js
const mar = require('./mar');
const app = mar();
app.start(3000);

2.mar类需要实现以下几点

  • 将koa的方法挂载到实例的$app属性上:this.$app = new koa()
  • 将controller挂载到实例的controller上:this.controller = initController()
  • 将Router挂载到实例的router上:this.router = Router()
  • 返回一个启动函数start
// mar/mar.js
const koa = require('koa');
const { initController, initRouter } = require('./mar-load');

class mar {
	constructor(conf) {
		this.$app = new koa(conf);
		this.controller = initController();
		this.router = initRouter();
		this.$app.use(this.router.routes());
	}
	start(port) {
		this.$app.listen(port, `[mar]Server is running at http://localhost:${port}`);
	}
}

在这里插入图片描述
此时,需要在 mar-load中定义initController,功能如下:
1.调用load函数,读取controller下的文件
2.对应读取出来的文件的键和值

const initController = () =>{
	const controllers = {};
	load('controller', (filename, controller) =>{
		controllers[filename] = controller;
	})
	return controoler = {};
}

在这里插入图片描述

  • 此时,只能监听 user 目录下的路由.
  • 使用console.log大法,在initRouter里面,将load('router')的结果打印出来
    在这里插入图片描述
    发现原因:
    1./mar/routes/index.js导出的是一个函数,而/mar/routes/user.js导出的是一个对象
    2.故后面Object.keys()方法是无法遍历’index.js’中的路由的
    3.需要改进initRouter方法如下
const initRouter = (app) => {
	const router = new Router();
	load('routes', (filename, routes) =>{
		routes = typeof routes === 'function' ? routes.app : routes;
		const prefix = filename === 'index' ? '' : `/${filename}`;
		Object.keys(routes).forEach(key =>{
			const [method, path] = key.split(' ');
			console.log(`正在映射地址: ${method.toLocaleUpperCase()}${prefix}${path}`);
			// 注册路由
            router[method](prefix + path, routes[key]);
		})
	})
	return router;
}

注:
1.此时在/mar/mar.js的构造函数中,应该将当前的this传入,即 ‘this.router = initRouter(this)’;
2.this代表的是使用new mar()生成的实例
在这里插入图片描述
至此,Controller层就实现了

发布了177 篇原创文章 · 获赞 22 · 访问量 2万+

猜你喜欢

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