这两天开始认真学习express,一下子从php转到express还是很不习惯的。
控制器这块,一般定义一个路由中间件是这样的
var Home = require(__rootdir + '/controllers/home');
router.get('/', Home.getIndex);
home.js
module.exports.getIndex = function(req,res) {
res.send('hello world!');
}
那么多个控制器如何共享一些方法呢?在基于类的面向对象写法中一般是创建一个控制器父类,一些通用的辅助方法都放在服控制器中,其他控制器继承它就ok了。
js的话通过原型继承也能实现,于是做了这样的改写。
1.创建"父类" controller.js
var controller = function(){}
module.exports = controller;
2.改造home.js
var controller = require('./controller');
module.exports.getIndex = function(req,res) {
res.send('hello world!');
}
module.exports.getIndex.prototype = controller.prototype;
看上去,我只要在controller的prototype中添加一些方法就可以共享给home了,然而随之而来又有一个问题,假如这些方法需要访问 req,res对象咋办?我只知道只有中间件才能直接访问到这几个对象。。那么必须想办法在中间件(home.getIndex)中把这几个对象反过来共享给其他所有方法…有点晕了。 总之,办法还是有的,继续改造咯。
-
controller.js
var controller = function(req,res,next){ this.req = req; this.res = res; this.next = next; } module.exports = controller;
2.改造home.js
var controller = require('./controller');
module.exports.getIndex = function() {
var handle = function(req,res,next){
var p = new controller(req,res,next);
res.send('hello world!');
}
return handle;
}
说实话,写到这里我也没兴趣去验证它能否运行了,太恶心了。
最后,我听别人说es6可以支持class了,赶紧去了解了一下,最终成功应用到项目里,改造成这样:
-
controller.js
class Controller { constructor(req,res,next) { this.req = req; this.res = res; this.next = next; } } module.exports = Controller;
2.home.js
var Controller = require( './controller');
class Home extends Controller {
getIndex() {
this.res.send('hello world');
}
}
module.exports = function(name){
return function(req,res,next){
var instance = new Home(req,res,next);
instance[name]();
};
};
3.路由
var Home = require(__rootdir + '/controllers/home');
router.get('/', Home('getIndex'));
es6的继承而已
这样写反而不伦不类,
@zstxt1989 你可以去看看另外一个框架Sails.js 的控制器
为啥module.exports.getIndex
直接 exports.getIndex
呀
通用方法在 controller 中的共享,我是通过加中间件的方式来做的。
用中间件的方式的话,劣势就是所有的 controller 都接收到了这个方法。
你这个方式通过继承可以只让特定的 controller 拥有某类方法。但是其实中间件的方式,也可以做到这一点的。。。做到之后,还是代码比你现在的继承方式清晰好懂。
@alsotang 通过中间件传递的话,是不是要把方法附着在request对象上呢?
@zstxt1989 是的啊,这样一来,还能直接操作 req 里面的一些属性,而不用外部传参了
我的通用方法都是抽象出通用函数, 然后在需要的地方调用就好了, 都写到原型链会造成所有的controller不管需要不需要, 都会收到这个方法
继承存在的意义本就不是 “重用”