今天由于分析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");