jquery-ui 分析2
今天由于分析jquery-ui-multiselect 再次读了jquery.ui.widget的代码;读完后很不淡定啊,其实我在想一个事情:jquery 的代码太灵活了,jquery-ui的核心依赖jquery.ui.widget的代码写的近乎诡异哦,太人才喽,哥要不要去学学面向对象的js框架比如dojo?
闲话不扯,先弄懂jquery-ui吧。简单写写学到的知识:
jquery -ui的插件体系里,所有的控件都依赖于ui.core 和ui.widget,是不是都继承他俩?这个“继承”看起来真的不能滥用哦。“继承“的感觉还真是不明显!
1:创建插件对象
$.widget.bridge 这个方法给了我们一段通用的创建对象的方法,什么dialog,progressbar等等都通过这个方法调用对象,看起来有点像继承,呵呵,不过真不是。
1 $.widget.bridge = function( name, object ) { 2 var fullName = object.prototype.widgetFullName || name; 3 $.fn[ name ] = function( options ) { 4 var isMethodCall = typeof options === "string", 5 args = slice.call( arguments, 1 ), 6 returnValue = this; 7 8 // allow multiple hashes to be passed on init 9 options = !isMethodCall && args.length ? 10 $.widget.extend.apply( null, [ options ].concat(args) ) : 11 options; 12 13 if ( isMethodCall ) { 14 this.each(function() { 15 //如果是方法调用。。。。 16 } 17 }); 18 } else { 19 this.each(function() { 20 //非方法调用的时候。。。。 21 }); 22 } 23 24 return returnValue; 25 }; 26 };
第三行:$.fn[ name ]
实际上相当于$.fn.命名空间, 好,一般读过插件代码的都知道它是用来创建新插件的。
第4,5行代码:
var isMethodCall = typeof options === "string", args = slice.call( arguments, 1 ),
对第一个参数进行判断,如果是string,表明这是方法调用。
args = slice.call( arguments, 1 ), 是获得第一个参数后面的参数。
2: 方法调用
2:方法调用;
通常我们写java,C#代码,方法调用是这样的:
new 类名().方法名(“参数”);
但是我们在实现jquery插件系统的时候,往往是这样:
$("selector").namespance("方法名",[参数列表]) 比如: $("div").button("open");
这么做看起来很奇怪,不过据翻阅各种资料,它的重要作用是防止命名空间的污染。
看这样一段代码:
假如写一个tooltip的插件:
1 (function( $ ){ 2 3 $.fn.tooltip = function( options ) { // 这样 }; 4 $.fn.tooltipShow = function( ) { // 是 }; //显示tooltip 5 $.fn.tooltipHide = function( ) { // 不好的 }; //隐藏tooltip 6 $.fn.tooltipUpdate = function( content ) { // 同学! }; //。。。 7 8 })( jQuery );
我们想这样写代码:
$("<div>").tooltip();
$("<div>").tooltipShow();
这样的危险在于,可能有人写了一个东东,
比如:
$("<div>").tooltipShow=function(){
func1:function(){}
}
好吧,直接的结果是,原来的代码$("<div>").tooltipShow();挂掉了。
3: 可以覆盖的方法
在jquery.ui.widget 中有些方法一般都会被基于它的控件所覆盖:
destroy():将widget实例从dom对象上移除,在开发widget的时候一般此方法是必须的。就是移除你自己在dom element上添加的样式和行为以及dom结构
options:在这里面保存的是widget的配置信息,在创建widget的时候需要设置一些配置参数。
element:就是widget作用的dom对象。
enable()和disable()这两个方法就是禁用和启用widget的。其实是修改options.disabled。
还有两个私有方法是创建widget的时候要重写的。
_create() 这个方法就是创建widget的方法,在页面调用widget的时候,就会执行此方法,来构建widget。Widget的绝大大多数行为和结构都是在这里创建的。
_init() ;
_create()方法在widget构建的时候执行,而_init()方法在构建和重新初始化的时候执行。而destroy方法则是在移除widget的时候被执行。在widget中,所有的私有方法都将加以"_"前缀
_setOption():此方法提供了options的属性的设置,一般情况下如果options里面的参数不需要特殊处理(校验,类型转换,以及设置属性的时候触发某一操作等)的时候不需要对此方法进行重写
分析widget的源码可以看到:
_create: $.noop,
_init: $.noop,
明摆着是让子控件来重写[不是调用哦]的,呵呵!然而,重写某些方法,可能会带来灾难性后果哦,比如_createWidget,看来jquery-ui对某些方法保护做的不好
前缀为"_"的方法,一般可以认为是私有方法,子控件调用不得。
因为有这段代码:
if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
return $.error( "no such method '" + options + "' for " + name + " widget instance" );
}
比如:
// 这行代码不会执行控件的任何方法 $("button").button("_create");