一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

jQuery UI Widget(1.8.1)工作原理

 四分之三光棍 2011-09-19
先看下代碼的相關注釋:
Javascript代碼 復制代碼 收藏代碼
  1. /*!  
  2.  * jQuery UI Widget 1.8.1  
  3.  *  
  4.  * Copyright (c) 2010 AUTHORS.txt (http:///about)  
  5.  * Dual licensed under the MIT (MIT-LICENSE.txt)  
  6.  * and GPL (GPL-LICENSE.txt) licenses.  
  7.  *  
  8.  * http://docs./UI/Widget  
  9.  */  
  10. (function( $ ) {   
  11.     
  12. var _remove = $.fn.remove;   
  13.     
  14. $.fn.remove = function( selector, keepData ) {   
  15.     return this.each(function() {   
  16.         if ( !keepData ) {   
  17.             if ( !selector || $.filter( selector, [ this ] ).length ) {   
  18.                 $( "*"this ).add( this ).each(function() {   
  19.                     $( this ).triggerHandler( "remove" );   
  20.                 });   
  21.             }   
  22.         }   
  23.         //dom元素在被刪除前,觸發(fā)一下remove事件,jquery框架本身沒有對元素刪除綁定事件   
  24.         return _remove.call( $(this), selector, keepData );   
  25.     });   
  26. };   
  27.     
  28. $.widget = function( name, base, prototype ) {   
  29.     var namespace = name.split( "." )[ 0 ],   
  30.         fullName;   
  31.     name = name.split( "." )[ 1 ];   
  32.     fullName = namespace + "-" + name;   
  33.     //比如ui.tab,上面的name='tab';fullName='ui-tab';   
  34.     
  35.     if ( !prototype ) {   
  36.         prototype = base;   
  37.         base = $.Widget;   
  38.     }   
  39.     //如果沒有prototype,那么prototype就是base參數(shù),實際base默認為$.Widget   
  40.     
  41.     // create selector for plugin   
  42.     $.expr[ ":" ][ fullName ] = function( elem ) {   
  43.         return !!$.data( elem, name );   
  44.     };   
  45.     
  46.     $[ namespace ] = $[ namespace ] || {};//是否有命名空間   
  47.     $[ namespace ][ name ] = function( options, element ) {//根據(jù)上面的例子,即初始化了$.ui.tab=func   
  48.         // allow instantiation without initializing for simple inheritance   
  49.         if ( arguments.length ) {   
  50.             this._createWidget( options, element );   
  51.         }   
  52.     };   
  53.     
  54.     var basePrototype = new base();//初始化,一般都是調用了new $.Widget()   
  55.     // we need to make the options hash a property directly on the new instance   
  56.     // otherwise we'll modify the options hash on the prototype that we're   
  57.     // inheriting from   
  58. //  $.each( basePrototype, function( key, val ) {   
  59. //      if ( $.isPlainObject(val) ) {   
  60. //          basePrototype[ key ] = $.extend( {}, val );   
  61. //      }   
  62. //  });   
  63.     basePrototype.options = $.extend( {}, basePrototype.options );//初始化options值,注意不需要深度拷貝   
  64.     $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {   
  65.         namespace: namespace,   
  66.         widgetName: name,   
  67.         widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,   
  68.         widgetBaseClass: fullName   
  69.     }, prototype );   
  70.     //為新的ui模塊創(chuàng)建原型,使用深度拷貝,在basePrototype上擴展一些模塊基本信息,在擴展prototype,比如ui.tabs.js中就是tab的擁有各種方法的大對象   
  71.     
  72.     $.widget.bridge( name, $[ namespace ][ name ] );//將此方法掛在jQuery對象上   
  73. };   
  74.     
  75. $.widget.bridge = function( name, object ) {   
  76.     $.fn[ name ] = function( options ) {   
  77.         var isMethodCall = typeof options === "string",   
  78.             args = Array.prototype.slice.call( arguments, 1 ),   
  79.             returnValue = this;   
  80.         //如果第一個參數(shù)是string類型,就認為是調用模塊方法   
  81.         //剩下的參數(shù)作為方法的參數(shù),后面會用到   
  82.     
  83.         // allow multiple hashes to be passed on init   
  84.         options = !isMethodCall && args.length ?   
  85.             $.extend.apply( null, [ true, options ].concat(args) ) :   
  86.             options;   
  87.         //可以簡單認為是$.extend(true,options,args[0],...),args可以是一個參數(shù)或是數(shù)組   
  88.     
  89.         // prevent calls to internal methods   
  90.         if ( isMethodCall && options.substring( 0, 1 ) === "_" ) {   
  91.             return returnValue;   
  92.         }   
  93.         //開頭帶下劃線的方法都是私有方法,不讓調用   
  94.     
  95.         if ( isMethodCall ) {//如果是調用函數(shù)   
  96.             this.each(function() {   
  97.                 var instance = $.data( this, name ),//得到實例,實例作為一個數(shù)據(jù)和元素關聯(lián)上   
  98.                     methodValue = instance && $.isFunction( instance[options] ) ?   
  99.                         instance[ options ].apply( instance, args ) ://如果實例和方法均存在,調用方法,把args作為參數(shù)傳進去   
  100.                         instance;//否則返回undefined   
  101.                 if ( methodValue !== instance && methodValue !== undefined ) {//如果methodValue不是jquery對象也不是undefined   
  102.                     returnValue = methodValue;   
  103.                     return false;//跳出each,一般獲取options的值會走這個分支   
  104.                 }   
  105.             });   
  106.         } else {//不是函數(shù)調用的話   
  107.             this.each(function() {   
  108.                 var instance = $.data( this, name );   
  109.                 if ( instance ) {//實例存在   
  110.                     if ( options ) {//有參數(shù)   
  111.                         instance.option( options );//調用option函數(shù),一般是設置狀態(tài)之類的操作   
  112.                     }   
  113.                     instance._init();//再次調用此函數(shù),根據(jù)options調整   
  114.                 } else {   
  115.                     $.data( this, name, new object( options, this ) );   
  116.                     //沒有實例的話,給元素綁定一個實例。注意這里的this是dom,object是模塊類   
  117.                 }   
  118.             });   
  119.         }   
  120.     
  121.         return returnValue;//返回,有可能是jquery對象,有可能是其他值   
  122.     };   
  123. };   
  124.     
  125. $.Widget = function( options, element ) {//所有模塊的基類   
  126.     // allow instantiation without initializing for simple inheritance   
  127.     if ( arguments.length ) {//如果有參數(shù),調用初始化函數(shù)   
  128.         this._createWidget( options, element );   
  129.     }   
  130. };   
  131.     
  132. $.Widget.prototype = {   
  133.     widgetName: "widget",   
  134.     widgetEventPrefix: "",   
  135.     options: {   
  136.         disabled: false  
  137.     },//上面的屬性會在創(chuàng)建模塊時被覆蓋   
  138.     _createWidget: function( options, element ) {   
  139.         // $.widget.bridge stores the plugin instance, but we do it anyway   
  140.         // so that it's stored even before the _create function runs   
  141.         this.element = $( element ).data( this.widgetName, this );//緩存實例,保存jquery對象   
  142.         this.options = $.extend( true, {},   
  143.             this.options,   
  144.             $.metadata && $.metadata.get( element )[ this.widgetName ],   
  145.             options );//參數(shù)處理   
  146.     
  147.         var self = this;   
  148.         this.element.bind( "remove." + this.widgetName, function() {   
  149.             self.destroy();   
  150.         });//注冊銷毀事件   
  151.     
  152.         this._create();//創(chuàng)建   
  153.         this._init();//初始化   
  154.     },   
  155.     _create: function() {},   
  156.     _init: function() {},   
  157.     
  158.     destroy: function() {//銷毀模塊:去除綁定事件、去除數(shù)據(jù)、去除樣式、屬性   
  159.         this.element   
  160.             .unbind( "." + this.widgetName )   
  161.             .removeData( this.widgetName );   
  162.         this.widget()   
  163.             .unbind( "." + this.widgetName )   
  164.             .removeAttr( "aria-disabled" )   
  165.             .removeClass(   
  166.                 this.widgetBaseClass + "-disabled " +   
  167.                 "ui-state-disabled" );   
  168.     },   
  169.     
  170.     widget: function() {//返回jquery對象   
  171.         return this.element;   
  172.     },   
  173.     
  174.     option: function( key, value ) {//設置選項函數(shù)   
  175.         var options = key,   
  176.             self = this;   
  177.     
  178.         if ( arguments.length === 0 ) {   
  179.             // don't return a reference to the internal hash   
  180.             return $.extend( {}, self.options );//返回一個新的對象,不是內部數(shù)據(jù)的引用   
  181.         }   
  182.     
  183.         if  (typeof key === "string" ) {   
  184.             if ( value === undefined ) {   
  185.                 return this.options[ key ];//取值   
  186.             }   
  187.             options = {};   
  188.             options[ key ] = value;//設置值   
  189.         }   
  190.     
  191.         $.each( options, function( key, value ) {   
  192.             self._setOption( key, value );//調用內部的_setOption   
  193.         });   
  194.     
  195.         return self;   
  196.     },   
  197.     _setOption: function( key, value ) {   
  198.         this.options[ key ] = value;   
  199.     
  200.         if ( key === "disabled" ) {//增加或是去除className   
  201.             this.widget()   
  202.                 [ value ? "addClass" : "removeClass"](   
  203.                     this.widgetBaseClass + "-disabled" + " " +   
  204.                     "ui-state-disabled" )   
  205.                 .attr( "aria-disabled", value );   
  206.         }   
  207.     
  208.         return this;   
  209.     },   
  210.     
  211.     enable: function() {   
  212.         return this._setOption( "disabled"false );   
  213.     },   
  214.     disable: function() {   
  215.         return this._setOption( "disabled"true );   
  216.     },   
  217.     
  218.     _trigger: function( type, event, data ) {   
  219.         var callback = this.options[ type ];   
  220.     
  221.         event = $.Event( event );   
  222.         event.type = ( type === this.widgetEventPrefix ?   
  223.             type :   
  224.             this.widgetEventPrefix + type ).toLowerCase();   
  225.         data = data || {};   
  226.     
  227.         // copy original event properties over to the new event   
  228.         // this would happen if we could call $.event.fix instead of $.Event   
  229.         // but we don't have a way to force an event to be fixed multiple times   
  230.         if ( event.originalEvent ) {//把原始的event屬性重新賦到event變量上   
  231.             for ( var i = $.event.props.length, prop; i; ) {   
  232.                 prop = $.event.props[ --i ];   
  233.                 event[ prop ] = event.originalEvent[ prop ];   
  234.             }   
  235.         }   
  236.     
  237.         this.element.trigger( event, data );   
  238.     
  239.         return !( $.isFunction(callback) &&   
  240.             callback.call( this.element[0], event, data ) === false ||   
  241.             event.isDefaultPrevented() );   
  242.     }   
  243. };   
  244.     
  245. })( jQuery );  

上面是jquery.ui.widget.js的源碼,jquery ui的所有模塊都是基于其中的widget方法進行擴展,使用統(tǒng)一的命名規(guī)范和編碼風格。
先來說一下原理:
$.widget此函數(shù)完成了對jQuery本身的擴展,根據(jù)第一個參數(shù)來確定模塊的命名空間和函數(shù)名;第二個參數(shù)確定模塊的基類(默認是$.Widget);第三個參數(shù)實現(xiàn)模塊本身的方法。比如標簽切換插件jquery.ui.tabs.js中開始:
$.widget(“ui.tabs”, {…});//這里只有兩個參數(shù),那么基類就默認是$.Widget
第一個參數(shù):”ui.tabs”用來表示在jQuery上選擇(或增加)一個命名空間,即如果jQuery.ui不存在,則定義jQuery.ui = {},然后在jQuery.ui上增加一個函數(shù),名稱為tabs.最后調用$.widget.bridge將tabs方法掛在jQuery對象上。這樣,所有的jquery對象將擁有tabs方法。

注意:jquery ui有嚴格的命名規(guī)范,每個控件對外只暴露一個借口??丶蟹椒ɑ驅傩酝ㄟ^向此借口傳遞不同參數(shù)來調用和獲取。

jquery ui的大部分控件是基于$.Widget基類實現(xiàn)的。所以一般我們做控件是都要重寫$.Widget類中的一些方法。一般來說,一個ui控件需要實現(xiàn)下列的方法或屬性:
屬性:
options 用來緩存控件各項參數(shù)
私有方法,使用“$(xx).tabs(私有方法)”這種方式來調用私有方法時會立刻返回,調用不能成功:
_create 控件初始化調用,多次調用$(xx).tabs()這樣不帶參數(shù)的方法只會執(zhí)行一次
_init 一般不用實現(xiàn),默認為空函數(shù),每次“$(xx).tabs()”這樣調用時會調用此方法
_setOption “$(xx).tabs(‘option’,xxx)”這種調用方式會調用此方法
公開方法:
destroy 銷毀模塊
option 設置或獲取參數(shù)
enable 啟用模塊功能
disable 禁用功能

幾乎所有的jquery ui控件都會重寫這些接口,同時增加控件相關的私有或公有方法。

記住,jquery ui的實例是和元素關聯(lián)起來的,作為數(shù)據(jù)保存起來了。暴露給用戶使用的只是jquery對象上增加的方法。一般我們不需要獲取ui的實例。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    欧美一区二区在线日韩| 日本人妻中出在线观看| 亚洲国产精品久久琪琪| 日韩午夜老司机免费视频| 一区二区三区人妻在线| 日韩欧美二区中文字幕| 欧美一区二区在线日韩| 亚洲专区一区中文字幕| 丁香六月婷婷基地伊人| 中文字幕日韩欧美亚洲午夜| 男人和女人干逼的视频| 国产日韩欧美在线播放| 老熟女露脸一二三四区| 午夜福利视频日本一区| 五月的丁香婷婷综合网| 日韩精品一级片免费看| 日韩黄色一级片免费收看| 国产精品视频一区二区秋霞| 成人精品日韩专区在线观看| 亚洲淫片一区二区三区| 欧洲自拍偷拍一区二区| 亚洲国产欧美精品久久| 最新国产欧美精品91| 国产精品视频一区二区秋霞| 熟妇久久人妻中文字幕| 香蕉网尹人综合在线观看| 中文字幕人妻一区二区免费| 偷自拍亚洲欧美一区二页| 国产精品一区二区丝袜| 欧美做爰猛烈叫床大尺度| 伊人久久青草地综合婷婷| 老司机精品国产在线视频| 伊人天堂午夜精品草草网| 色哟哟精品一区二区三区| 国产精品一区二区日韩新区| 91老熟妇嗷嗷叫太91| 欧美av人人妻av人人爽蜜桃| 欧美成人黄色一级视频| 亚洲国产欧美精品久久| 亚洲日本中文字幕视频在线观看| 国产成人精品综合久久久看 |