先看下代码的相关注释:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
/*! * jQuery UI Widget 1.8.1 * * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Widget */ ( function ( $ ) { var _remove = $.fn .remove ; $.fn .remove = function ( selector, keepData ) { return this .each ( function ( ) { if ( ! keepData ) { if ( ! selector || $.filter ( selector, [ this ] ) .length ) { $( "*" , this ) .add ( this ) .each ( function ( ) { $( this ) .triggerHandler ( "remove" ) ; } ) ; } } //dom元素在被删除前,触发一下remove事件,jquery框架本身没有对元素删除绑定事件 return _remove.call ( $( this ) , selector, keepData ) ; } ) ; } ; $.widget = function ( name , base, prototype ) { var namespace = name .split ( "." ) [ 0 ] , fullName; name = name .split ( "." ) [ 1 ] ; fullName = namespace + "-" + name ; //比如ui.tab,上面的name='tab';fullName='ui-tab'; if ( ! prototype ) { prototype = base; base = $.Widget ; } //如果没有prototype,那么prototype就是base参数,实际base默认为$.Widget // create selector for plugin $.expr [ ":" ] [ fullName ] = function ( elem ) { return !! $.data ( elem, name ) ; } ; $[ namespace ] = $[ namespace ] || { } ; //是否有命名空间 $[ namespace ] [ name ] = function ( options, element ) { //根据上面的例子,即初始化了$.ui.tab=func // allow instantiation without initializing for simple inheritance if ( arguments.length ) { this ._createWidget( options, element ) ; } } ; var basePrototype = new base( ) ; //初始化,一般都是调用了new $.Widget() // we need to make the options hash a property directly on the new instance // otherwise we'll modify the options hash on the prototype that we're // inheriting from // $.each( basePrototype, function( key, val ) { // if ( $.isPlainObject(val) ) { // basePrototype[ key ] = $.extend( {}, val ); // } // }); basePrototype.options = $.extend ( { } , basePrototype.options ) ; //初始化options值,注意不需要深度拷贝 $[ namespace ] [ name ] .prototype = $.extend ( true , basePrototype, { namespace : namespace , widgetName: name , widgetEventPrefix: $[ namespace ] [ name ] .prototype .widgetEventPrefix || name , widgetBaseClass: fullName } , prototype ) ; //为新的ui模块创建原型,使用深度拷贝,在basePrototype上扩展一些模块基本信息,在扩展prototype,比如ui.tabs.js中就是tab的拥有各种方法的大对象 $.widget .bridge ( name , $[ namespace ] [ name ] ) ; //将此方法挂在jQuery对象上 } ; $.widget .bridge = function ( name , object ) { $.fn [ name ] = function ( options ) { var isMethodCall = typeof options === "string" , args = Array.prototype .slice .call ( arguments, 1 ) , returnValue = this ; //如果第一个参数是string类型,就认为是调用模块方法 //剩下的参数作为方法的参数,后面会用到 // allow multiple hashes to be passed on init options = ! isMethodCall && args.length ? $.extend .apply ( null , [ true , options ] .concat ( args) ) : options; //可以简单认为是$.extend(true,options,args[0],...),args可以是一个参数或是数组 // prevent calls to internal methods if ( isMethodCall && options.substring ( 0 , 1 ) === "_" ) { return returnValue; } //开头带下划线的方法都是私有方法,不让调用 if ( isMethodCall ) { //如果是调用函数 this .each ( function ( ) { var instance = $.data ( this , name ) , //得到实例,实例作为一个数据和元素关联上 methodValue = instance && $.isFunction ( instance[ options] ) ? instance[ options ] .apply ( instance, args ) : //如果实例和方法均存在,调用方法,把args作为参数传进去 instance; //否则返回undefined if ( methodValue !== instance && methodValue !== undefined ) { //如果methodValue不是jquery对象也不是undefined returnValue = methodValue; return false ; //跳出each,一般获取options的值会走这个分支 } } ) ; } else { //不是函数调用的话 this .each ( function ( ) { var instance = $.data ( this , name ) ; if ( instance ) { //实例存在 if ( options ) { //有参数 instance.option ( options ) ; //调用option函数,一般是设置状态之类的操作 } instance._init( ) ; //再次调用此函数,根据options调整 } else { $.data ( this , name , new object( options, this ) ) ; //没有实例的话,给元素绑定一个实例。注意这里的this是dom,object是模块类 } } ) ; } return returnValue; //返回,有可能是jquery对象,有可能是其他值 } ; } ; $.Widget = function ( options, element ) { //所有模块的基类 // allow instantiation without initializing for simple inheritance if ( arguments.length ) { //如果有参数,调用初始化函数 this ._createWidget( options, element ) ; } } ; $.Widget .prototype = { widgetName: "widget" , widgetEventPrefix: "" , options: { disabled: false } , //上面的属性会在创建模块时被覆盖 _createWidget: function ( options, element ) { // $.widget.bridge stores the plugin instance, but we do it anyway // so that it's stored even before the _create function runs this .element = $( element ) .data ( this .widgetName , this ) ; //缓存实例,保存jquery对象 this .options = $.extend ( true , { } , this .options , $.metadata && $.metadata .get ( element ) [ this .widgetName ] , options ) ; //参数处理 var self = this ; this .element .bind ( "remove." + this .widgetName , function ( ) { self.destroy ( ) ; } ) ; //注册销毁事件 this ._create( ) ; //创建 this ._init( ) ; //初始化 } , _create: function ( ) { } , _init: function ( ) { } , destroy: function ( ) { //销毁模块:去除绑定事件、去除数据、去除样式、属性 this .element .unbind ( "." + this .widgetName ) .removeData ( this .widgetName ) ; this .widget ( ) .unbind ( "." + this .widgetName ) .removeAttr ( "aria-disabled" ) .removeClass ( this .widgetBaseClass + "-disabled " + "ui-state-disabled" ) ; } , widget: function ( ) { //返回jquery对象 return this .element ; } , option: function ( key, value ) { //设置选项函数 var options = key, self = this ; if ( arguments.length === 0 ) { // don't return a reference to the internal hash return $.extend ( { } , self.options ) ; //返回一个新的对象,不是内部数据的引用 } if ( typeof key === "string" ) { if ( value === undefined ) { return this .options [ key ] ; //取值 } options = { } ; options[ key ] = value; //设置值 } $.each ( options, function ( key, value ) { self._setOption( key, value ) ; //调用内部的_setOption } ) ; return self; } , _setOption: function ( key, value ) { this .options [ key ] = value; if ( key === "disabled" ) { //增加或是去除className this .widget ( ) [ value ? "addClass" : "removeClass" ] ( this .widgetBaseClass + "-disabled" + " " + "ui-state-disabled" ) .attr ( "aria-disabled" , value ) ; } return this ; } , enable: function ( ) { return this ._setOption( "disabled" , false ) ; } , disable: function ( ) { return this ._setOption( "disabled" , true ) ; } , _trigger: function ( type, event, data ) { var callback = this .options [ type ] ; event = $.Event ( event ) ; event.type = ( type === this .widgetEventPrefix ? type : this .widgetEventPrefix + type ) .toLowerCase ( ) ; data = data || { } ; // copy original event properties over to the new event // this would happen if we could call $.event.fix instead of $.Event // but we don't have a way to force an event to be fixed multiple times if ( event.originalEvent ) { //把原始的event属性重新赋到event变量上 for ( var i = $.event .props .length , prop; i; ) { prop = $.event .props [ -- i ] ; event[ prop ] = event.originalEvent [ prop ] ; } } this .element .trigger ( event, data ) ; return ! ( $.isFunction ( callback) && callback.call ( this .element [ 0 ] , event, data ) === false || event.isDefaultPrevented ( ) ) ; } } ; } ) ( jQuery ) ; |
上面是jquery.ui.widget.js的源码,jquery ui的所有模块都是基于其中的widget方法进行扩展,使用统一的命名规范和编码风格。
先来说一下原理:
$.widget此函数完成了对jQuery本身的扩展,根据第一个参数来确定模块的命名空间和函数名;第二个参数确定模块的基类(默认是$.Widget);第三个参数实现模块本身的方法。比如标签切换插件jquery.ui.tabs.js中开始:
$.widget(“ui.tabs”, {…});//这里只有两个参数,那么基类就默认是$.Widget
第一个参数:”ui.tabs”用来表示在jQuery上选择(或增加)一个命名空间,即如果jQuery.ui不存在,则定义jQuery.ui =
{},然后在jQuery.ui上增加一个函数,名称为tabs.最后调用$.widget.bridge将tabs方法挂在jQuery对象上。这样,
所有的jquery对象将拥有tabs方法。
注意:jquery ui有严格的命名规范,每个控件对外只暴露一个借口。控件所有方法或属性通过向此借口传递不同参数来调用和获取。
jquery ui的大部分控件是基于$.Widget基类实现的。所以一般我们做控件是都要重写$.Widget类中的一些方法。一般来说,一个ui控件需要实现下列的方法或属性:
属性
:
options 用来缓存控件各项参数
私有方法
,使用“$(xx).tabs(私有方法)”这种方式来调用私有方法时会立刻返回,调用不能成功:
_create 控件初始化调用,多次调用$(xx).tabs()这样不带参数的方法只会执行一次
_init 一般不用实现,默认为空函数,每次“$(xx).tabs()”这样调用时会调用此方法
_setOption “$(xx).tabs(‘option’,xxx)”这种调用方式会调用此方法
公开方法
:
destroy 销毁模块
option 设置或获取参数
enable 启用模块功能
disable 禁用功能
几乎所有的jquery ui控件都会重写这些接口,同时增加控件相关的私有或公有方法。
记住,jquery ui的实例是和元素关联起来的,作为数据保存起来了。暴露给用户使用的只是jquery对象上增加的方法。一般我们不需要获取ui的实例。
相关推荐
[精华]网站论坛源码C# Jquery,完全自制,有很多jquery自己写的插件[精华]网站论坛源码C# Jquery,完全自制,有很多jquery自己写的插件
资源名称:jquery1.7 中文手册 CHM文档(附jquery1.82 chm手册)内容简介:因国内jquery中文手册更新太慢了,等了一段时间实在等不下去了,干脆自己动手做一个丰衣足食,时刻更新. 最后感谢Shawphy提供1.4.1版,jehn提供...
jquery自己写的文件目录,HttpServlet+js+jsp
jquery, 就是 jquery, 自己保存下。 以后都是vue了
仿照着jquery写了自己的框架,供新手参考
jquery自己整理手册
通过对JQuery使用的分析,实现一个简版的自己的JQuery
教你如何做一个自己的jQuery插件,jQuery扩展
一些JQuery特效, 自己写的, 想下就下, 没用我不会传上去!
<锋利的jquery>电子书的实验源码,用于自己的学习。jquery是js的超集,平时的开发过程中,原生的js用的倒没有jquery多
自己用JQuery写的一个锁屏加弹出模态窗口,里面包含有三种锁屏类型,能满足绝大部分WEB开发应用,是一套很漂亮的类型.
我们实习的时候,团队中各组员分别学习并总结的劳动成果,JQuery基础教程第2版(人民邮电出版社),很全面的知识总结,现在我拿来,分享给想学习JQuery的求知者,积分要的不多,也算是给我们劳动成果的一点回报,...
jQuery图片转换 换灯片 jQuery jQuery换灯片 可以试一下 自己的网站看能不能用上
自己写的jQuery分页根据json分页
这是我自己从网站上下载的整站jquery帮助文档api;1.11.2
jquery easy-ui的整体文件包,包括树,表单,表格等等,有demo,可以看相关demo后自己导入到项目用。
jQuery 常用组件打包下载! 内含有: jquery.1.1.4.core.zip --jQuery最新核心代码 jquery.calendar.zip --日历组件 jquery.menu.zip ...为了方便自己和方便大家,特别打包下载!懒得去官方网站逐个找!
jquery ui包 效果不错,只是为了自己保存.官网下载的,大家想要的话 也可以下载啊
jquery 中文文档说明,自己下载看看.
或是您曾经向自己的Web页面上添加过一些脚本,但想以一种更好的方式来实现它们?本书非常适合您。《JavaScript&jQuery;交互式Web前端开发》不仅向您展示如何阅读和编写JavaScript代码,同时还会以一种简单且视觉化的...