但有时候实现不像单体这么简单,比如在一个复杂的页面中包含有多个逻辑,多个逻辑中都有各自的命名空间,每个命名空间有自己实现的模块,每个模块依赖于其他子模块。这样一个页面的代码应当如何规划?其实类似这样复杂的页面代码的规划是一个很有渊源的话题,应当专门花时间来讨论,总言之,简单单体用作逻辑的命名空间,函数单体用作简单构造,比如实现模块中的一个内聚但不重用的子模块,原型单体用来专门封装一个高重用率的组件。
在开发过程中,使用一个对象的时候,往往不是初始化一次就不管了,页面交互过程中也会有对这个对象的重新生成和调用。因此在yui3这样的闭包中应当注意将对象搞成全局的,可以通过hook抓得到。但最常用的是render和init,init期望参数一次传递完,render期望能重新传递一些状态相关的参数。在构造对象的时候,传参和渲染应当分离,因为有时我们只会很粗暴的new sth(config)完事,那如果对象状态更改需要重新渲染难道要重新new一遍?所以在构造完成后建议返回对象本身,然后再执行render,例如:
var k = new sth(config).render();
当需要重新渲染这个对象的时候则只需render即可,render可以带去新的参数
k.render(new_config);
而有时我们则希望增加init,以便让代码更加语义,init意指初始化,render意指渲染。这里的初始化和渲染语义很接近,在实现上有一点差别,在new的时候会执行init,init包含初始化参数和render,init中的初始化参数若有留空则需一些默认值替代,在render中的参数初始化则只是覆盖原有参数。为此用两个函数来负责两种参数的处理:buildParam和parseParam,buildParam中负责构造所有的必要参数。在tb的新项目中写的simpleditor模块用了这种结构:
YUI.namespace('T.tbwidget.simpleditor');
YUI.add('t-simpleditor',function(Y){
T.tbwidget.simpleditor = function(){
this.init.apply(this,arguments);
};
//扩展prototype
Y.mix(T.tbwidget.simpleditor, {
buildParam:function(cfg){
var that = this;
//初始化时的必要字段
var id = that.id = cfg.id;
//初始化时的可选字段
var smtemplet = that.smtemplet = (typeof cfg.smtemplet == 'undefined')?'[face{$n}]':cfg.smtemplet;
return {
id:id,
smtemplet:smtemplet
};
},
parseParam:function(cfg){
var that = this;
var cfg = cfg || {};
//处理临时参数
var id = typeof cfg.id == 'undefined'?that.id:cfg.id;
var smtemplet = (typeof cfg.smtemplet == 'undefined')?that.smtemplet:cfg.smtemplet;
return {
id:id,
smtemplet:smtemplet
};
},
render:function(cfg){
var param = this.parseParam(cfg);
//初始化代码...
},
init:function(cfg){
this.buildParam(cfg);
this.render.call(this,cfg);
},
otherFoo:function(){
}
}, 0, null, 4);
});在构造的时候调用了一次init,就像这样
T.tbwidget.simpleditor = function(){
this.init.apply(this,arguments);
};这样有一个好处,就是若该模块用到一些依赖的时候,只需加一个loader,在loader完成之后执行init就可以了,在ebook项目中的评论组件就是用这种方法,执行init之前先加载皮肤。
T.tbwidget.tbrr = function(){
var that = this;
var args = arguments;
var skin = (typeof arguments[0].skin == 'undefined')?'':arguments[0].skin;
YUI({modules:{
'tbrr-skin':{
fullpath:skin,
type:'css'
}
}}).use('tbrr-skin',function(Y){
that.init.apply(that,args);
});
};让我们在返璞归真一下,实现一个最简单的链式调用,在每次函数调用结束后都返回自己,像这样
var mojoClass = function(){
this.render = function(){
return this;
};
this.init = function(){
return this;
};
this.buildParam = function(){};
this.parseParam = function(){};
};what's comming next?
js设计模式之桥接
js设计模式之单体
页面逻辑和模块
库(Library) or 框架(Framework)
to be continue...
[ view entry ] ( 31795 views ) | permalink |




( 3 / 163 )




