模块化始终是提升项目代码可维护性的首选,各个语言实现模块化的具体方式都有一些差别。在javascript当中,可以利用Object来实现页面功能块的模块化。
比如,页面上有一块表格内容用于显示一条一条的用户数据,然后最后一列是“修改”、“删除”操作,那么这个功能块可以大致写成如下结构:
var userTable = {
init: function(params) {
// 初始化功能块(参数调整、渲染界面样式、缓存DOM节点、填充数据、绑定事件等等)
this._renderData(this._data);
this._bindEvent();
},
_bindEvent: function() {
// 绑定事件(修改、删除等等)
},
_renderData: function(data) {
// 填充数据
}
};
如上代码,在DOM ready的时候,就可以直接调用userTable.init()来展示这个功能块了。
但是,这里有两个问题还没解决:
对于第一个问题,解决很简单,userTable直接向外部提供API即可,此时代码如下:
var userTable = {
init: function(params) {
// 初始化功能块(参数调整、渲染界面样式、缓存DOM节点、填充数据、绑定事件等等)
this._renderData(this._data);
this._bindEvent();
},
_bindEvent: function() {
// 绑定事件(修改、删除等等)
},
_renderData: function(data) {
// 填充数据
},
/**
* 为外部提供的API,用于刷新当前用户功能块的数据
*/
refresh: function() {
// 刷新用户数据
}
};
对于第二个问题,则是借助于事件机制了。这种事件机制其实在很多框架或库中都有实现(jquery、backbone等),此处暂且实现一个小型的事件机制。
在eventDealer对象中,有基本的on、trigger、off方法,分别用于注册事件、触发事件、取消注册事件。
借助于eventDealer,该功能区的代码可升级为:
var userTable = Object.create(eventDealer, {
init: function(params) {
// 初始化功能块(参数调整、渲染界面样式、缓存DOM节点、填充数据、绑定事件等等)
this._renderData(this._data);
this._bindEvent();
},
_bindEvent: function() {
// 绑定事件(修改、删除等等)
var _this = this;
this._modifyNode.on('click', function() {
// 执行修改操作(访问后端接口之类的)
// 在修改操作完成之后(此处可能会涉及到异步回调,请读者自己留意下)
_this.trigger('modified', data);
});
},
_renderData: function(data) {
// 填充数据
},
/**
* 为外部提供的API,用于刷新当前用户功能块的数据
*/
refresh: function() {
// 刷新用户数据
}
});
userTable继承自eventDealer,然后自然就有了eventDealer的能力。同时,以上代码在_bindEvent函数中,完成修改操作之后,调用了trigger方法,触发了modified事件,如果外部对这个事件感兴趣,则可以事先注册相应的回调函数:
userTable.on('modified', function(data) {
// do something
});
由此,两个问题得到了解决,用户功能块与外部耦合度就很低了。