通过原生html+css就可以写出基本的组件,比如select,很简单就可以写一个符合标准的组件
我做了很长时间java程序猿,配合jsp中的jstl,很简单的创建原生的html,再加上原生的事件,一个页面直接手工
但如果抛开后端生成html的能力,由js生成html,情况产生了微妙的变化
js只赋予html交互的能力,并没有对html进行增强,他对html标签的增强仅限于此,出于复用的方式,我们需要对js组件化(如果设计到select,table,html这些标签,我更愿意叫脚本化标签)
出于复用的目的,写一个简单的jquery插件
这样用起来就简单多了,他现在还很脆弱,任何一个小需求都能整死他,至少他缺少事件的能力,从对象角度看标签完全具有属性,方法和事件,我们的小组件也缺乏这三样基本能力
属性能力
传递过去的参数及其展示的参数的保存位置,有很多地方可以去保存,最简单的就是直接赋值给组件,没有被复用的属性将会极大的消耗性能,至少目前都会选择使用数据存储的方式对组件的属性进行保存,而非直接赋值(对属性的处理,算是js比较特殊的地方),jquery的数据存储方式也是比较流行的方式(这有两种实现,这些实现也都是为了解决组件属性存放问题的解决方案)
//这是一种最为粗暴的方式,原因参考数据存储 $.fn.combobox=function(options){ this.options=options; } //jquery的解决方案,需要的时候 $(this).data("options") $.fn.combobox=function(options){ $(this).data("options",options); }
方法能力
必须至于原形之中,用于方法的共享,如果使用原形,就得注意内部使用new创建,$().combobox()后,可以直接使用方法
(function($){ function Combobox(options){ //除了简单必要的属性至于this中,大多数属性还丢到其相关标签的$().data中 this.options=options; this.create(options.data) } Combobox.prototype.getValue=function(){ return this.options; } Combobox.prototype.create(data){ for(var i=0;i"+data[i].text+"") } } $.fn.combobox=function(options){ //流行的无new创建组件 return new Combobox(options); } $.fn.combobox.Constructor = Combobox })($)
当然也可以将方法直接负载构造方法上,而后提供一个统一的入口(一般就是构造方法),进行方法的调用,这种方式没有new,看似也没有原形,使用了js中一切都是对象,一切都可以赋值的特性,除了重写$.fn.combobox比较麻烦外(你会把method给干掉),完全无死角
(function($){ function create(jq,data){ for(var i=0;i"+data[i].text+"") } } $.fn.combobox=function(options){ if(typeof options === "string"){ $(this).data("options",options); return create(this.options) } var method=$.fn.combobox.method[options] method||method() } $.fn.combobox.method={ getOptions:function(jq){ return $(this).data("options"); } } })($)
事件能力
事件能力必须依赖于构建对象时的绑定,他是一个方法,只是绑到了原生方法中,会由系统调用,并传递参数,仅此而已(可以的话我想说,这就是实现了一个系统级的接口,你可以调用,但你无法保证参数的质量)
(function($){ function create(jq,data){ for(var i=0;i"+data[i].text+"") } } function bind(jq,options){ if(options.onSelect){ options.onBeforeSelect(jq); jq.on("select",options.onSelect); options.onAfterSelect(jq); } } $.fn.combobox=function(options){ if(typeof options === "string"){ $(this).data("options",options); create(this.options) bind(this,options) return } var method=$.fn.combobox.method[options] method||method() } $.fn.combobox.method={ getOptions:function(jq){ return $(this).data("options"); } } })($)
好了,将它们实现,我们第一个jquery组件也就诞生了,回头在看一下实现,这个组件只是对select这个html标签,脚本化,我们可以使用js动态且方便的生成原生的html标签,优势在于原生,缺点在于没有增强,需要checkbox的需求就能搞死你(我一直认为checkbox+select完全无意义,浪费cpu),再来一个select+tree,估计得疯掉一票...这个时候就不得不对这个组件进行增强,比如这里,我们在其内部可能会使用div甚至ul进行实现,而非传统的select(这正好也解释了为什么是combobox而非select)
使用增强的方式可以实现更多的酷炫功能,遗憾的是每个组件实现的思路完全不一致,这会限制组件的结构,这种结构也会反过来影响css,原生的标签很容易替换css,而增强过的标签很难更换一个皮肤,除非你很熟悉这种组件结构
可以的话,我只想将标准的标签进行脚本化(放在html上纯原生,即只做标签的交互),以方便我应付不同的UI,否则,即使组件化的封装减化了功能实现,超蛋疼的皮肤修改也会让人菊紧一整天