jquery-ui-widget
2015-04-22 16:35
281 查看
编写jQueryUI插件(widget)
使用jQueryUI的widget来写插件,相比于基本的jquery插件有一些好处:*方便实现继承,代码重用
*默认是单例
*widget已经给你实现好的一些常用方法,例如destroy
带来好处的同时也带来了荆棘和陷阱,本文的目的就是梳理这些荆棘,标出哪里有陷阱。
基本知识:命名规范,public,private,this,this.element
如何开始写一个widget呢?模板如下:(function($){ //utilityfunctions(won’tbeinherited) functionfoo(){} $.widget('命名空间.插件名',$.继承插件的命名空间.插件名,{/*snip*/}); })(jQuery);
其中命名空间是可选的,要不要继承别的widget也是可选的。大头是后面snip的部分,这也是下文要讲的。
一般来说工具函数写在widget外面比较合适,但如果你想要这些工具函数被子类继承,则需要写在widget里面。
写在widget里面的,就有public和private之分,规则是:
public方法首字符不是_
private方法首字符是_
当调用方法时,会先判断是否以_开头,如果是则不执行调用。
如果我非要在外面调用private方法,该怎么做?并非一点办法也没有:
varinstance=$('<div>'); instance.mywidget('publicFunction');//work instance.mywidget('_privateFunction');//silentlyfail instance.data('mywidget')._privateFunction();//work $.mynamespace.mywidget.prototype._privateFunction();//work
在widget内,this表示的是什么?我们在widget的一个public函数内用console.log(this)打出来瞧瞧:
日志显示,this是一个$.widget.$.(anonymousfunction).(anonymousfunction)
this.element是变成widget的那个jQuery对象,如果要用jquery的方法,往往首先要取到jquery对象。
this.options是插件的选项,下文会详解。
this.__proto__包含了插件中定义的所有public和private函数,以及继承过来的方法。
这里简单介绍一下__proto__:每个对象都会在其内部初始化一个属性,就是__proto__,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就这样一直找下去,也就是我们平时所说的原型链的概念。
_create_initdestroy
widgetfactory实现了一种单例模式,即不允许在同一个jQuery对象上多次实例化。当调用$(XX).widgetName()进行初始化的时候,会执行以下代码(源码截取自jquery.ui.widget.js):
varinstance=$.data(this,name);//从widget自身取出名字为name的数据
if(instance){
instance.option(options||{})._init();//若该数据已经存在则只调用_init
}else{
$.data(this,name,newobject(options,this));//若数据还没有则新建一个实例,并将实例保存
}
当调用$(XX).widgetName(‘destroy’)进行销毁的时候,执行以下代码(源码截取自jquery.ui.widget.js):
this.element
.unbind("."+this.widgetName)
.removeData(this.widgetName);//删除在create时保存的数据
有一个removeData的操作,那么下次调用$(XX).widgetName()就会重新实例化了。
需要注意的是,destroy方法在jquery.ui.widget.js中是有默认实现的,而_create和_init没有实现。因此如果用自己的方法覆盖destroy,不要忘记调用默认的:
destory:function(){
console.log('destory');
//calltheoriginaldestroymethodsinceweoverwroteit
$.Widget.prototype.destroy.call(this);
}
以下示例代码验证_create和_init的区别以及destroy的作用:
varmw=$('#test').myWidget();//_create_init
mw=$('#test').myWidget();//_init
mw.myWidget('destory');
mw=$('#test').myWidget();//_create_init
那么在_create和_init以及destroy里分别应该做什么:
_create:生成HTML,事件绑定。_init:执行默认的初始化动作,例如把页面变成初始状态。
destory:调用$.Widget.prototype.destroy.call(this),删除HTML。
注意:绑定事件要注意给事件名加命名空间后缀:例如.bind('mouseenter.mywidget',this._hover)
options
选项,在widget中的定义是options,而在调用时是option,注意定义的时候有s,调用的时候没s。定义:
option
s
:{
field1:'default',
function1:function(){
console.log('defaultoptionfunction1');
}
},
调用:
$('#test').mywidget('option','field1',2);
widget默认实现了两个函数:_setOptions和_setOption,_setOptions的实现就是对每个要修改的option调用_setOption,也就是说真正修改的动作在_setOption里。因此,如果要重写_setOption函数,则一定不要忘记写:
$.Widget.prototype._setOption.apply(this,arguments);
_setOptions和_setOption这俩函数什么时候被调用呢?用下面这个例子来说明。
例如有这样的_setOption和_setOptions:
_setOption:function(key,value){
console.log('_setOption:key=%svalue=%s',key,value);
$.Widget.prototype._setOption.apply(this,arguments);
},
_setOptions:function(options){
varkey;
console.group('_setOptions');
for(keyinoptions){
this._setOption(key,options[key]);
}
console.groupEnd();
returnthis;
},
以及一个打印options值的函数printOptions:
printOptions:function(){
console.group('options');
console.log('field1:%s',this.options.field1);
console.log('function1:%s',this.options.function1);
console.groupEnd();
},
我们像下面这样调用:
varinstance=$('<div>');
//createwidgetwithdefaultoptions
console.group();
instance.mywidget();
instance.mywidget('printOptions');
console.groupEnd();
//createwidgetwithspecifiedoptions
instance.mywidget('destroy');
console.group();
varopts={
field1:'specified',
function1:function(){
console.log('specifiedoptionfunction1');
},
};
instance.mywidget(opts);
instance.mywidget('printOptions');
console.log('-------------');
instance.mywidget(opts);
console.groupEnd();
//modifyoptions
console.group();
instance.mywidget('option','field1',2);
instance.mywidget('printOptions');
console.groupEnd();
打出的日志如下:
日志分为三大块。
第一块是不使用options来初始化,可以看到直接使用定义里默认的options,是不调用_setOption的。
第二块是使用options来初始化,这一块做了两个实验(日志中用--------将两块分隔),第一个实验是完全重建(_create,_init),从日志可以看到并没有调用_setOption;第二个实验只是重新初始化(_init),用的options都一样,从日志可以看到它调用了_setOption,且在_init之前调用的。
第三块不是初始化,而仅仅是修改option值,可以清楚看到调用了_setOption。
何时会调用_setOption的结论:
1.像instance.mywidget('option','field1',2);这样显式设置option时。2.带着options初始化时:
如果实例不存在,即需要调用_create,则不调用_setOption;
如果实例已存在,仅需要调用_init,则会在调用_init之前调用_setOption。
_trigger
注意这个_trigger是jQueryUIwidgetfactory里的,和jQuery里$.fn命名空间下的trigger函数不是一个东西(后者不带下划线)。_trigger一般用来回调用户传入options的callback。
在插件内部调用_trigger(‘myEvent’)即相当于调用options里面的myEvent这个回调函数。
要改动options里的eventhandler应该怎么做呢?不要使用bind/unbind,而是去修改options:
//bind(overwrite,notaddeventhandler)
mw.myWidget('option','myEvent',function(event,ui){
console.log('newimplement');
});
//unbind
mw.myWidget('option','myEvent',null);
总结一下:
this._trigger(‘eventName’)是widget特有的,用于调用options里定义的callback。
this.element.trigger(‘eventName’)是jQuery的,可参考jQuery的事件的用法。(其中this.element是表示该插件的jQuery对象)
一个_trigger的样例:
//模板
this._trigger("callbackName",[eventObject],[uiObject])
callbackNameThenameoftheeventyouwanttodispatch
eventObject(Optional)An(mocked)eventobject.
_triggerwrapsthisobjectandstoresitin
event.originalEventTheuserreceivesanobjectwithevent.type==
this.widgetEventPrefix+"eventname"
uiObject(Optional)Anobjectcontainingusefulpropertiestheusermayneedtoaccess.Protip:Useamethodlike
._uitogenerateobjectswithaconsistentschema.
//调用样例
this._trigger("hover",e/*e.type=="mouseenter"*/,{hovered:$(e.target)});
//Theusercansubscribeusinganinitoption
$("#elem").filterable({hover:function(e,ui){}});
//Orwithtraditionaleventbinding/delegation
$("#elem").bind("filterablehover",function(e,ui){});
相关文章推荐
- jQuery UI API - 可拖拽小部件(Draggable Widget)(转)
- jQueryUI Plugin TableSorter的2个widget扩展
- Using the jQuery UI Dialog widget for confirmation windows
- jQueryUI Plugin TableSorter的2个widget扩展
- jQuery UI MultiSelect Widget的使用
- jQuery UI API - 工具提示框部件(Tooltip Widget)
- jquery ui widget 源代码分析
- jQuery UI API - 工具提示框部件(Tooltip Widget)
- jquery.ui.widget详解
- jQuery ui widget tutorial
- jQuery插件 -- UI插件Tabs Widget 1.10
- jquery ui widget 源码分析
- Jquery ui widget中的_create(),_init(),destroy()
- jQuery UI widget factory
- 通过扩展jQuery UI Widget Factory实现手动调整Accordion高度
- 下拉多选框的使用方法(jQuery UI MultiSelect Widget)
- jQuery UI MultiSelect Widget使用实现步骤
- jQuery:jQuery UI API - 自动完成部件(Autocomplete Widget)
- https://github.com/ehynds/jquery-ui-multiselect-widget
- jQuery UI Widget 原理