jQuery扩展插件

什么是jQuery插件?

扩展jQuery原型对象的一个方法(jQuery插件是jQuery对象的一个方法)
jQuery插件的使用方式就是jQuery对象方法的调用。

jQuery.fn=jQuery.prototype

使用(jQuery插件如何使用?)

jQuery.fn.myPlugin = function() {

    // 插件的具体内容放在这里

};

$的冲突

把 jQuery 传递给 IIFE(立即调用函数),并通过它映射成 $ ,这样就避免了在执行的作用域里被其它库所覆盖。

(function( $ ) {
   $.fn.myPlugin = function() {
   
       // 插件的具体内容放在这里
   
   };
})( jQuery );

加分号的意义:
以 “(”、“[”、“/”、“+”、或 “-” 开始,那么它极有可能和前一条语句合在一起解释。
------《JavaScript 权威指南》
避免js代码压缩时出错

上下文中的this指向

在插件函数的立即作用域中,关键字 this 指向调用插件的 jQuery 对象。

(function( $ ){
    $.fn.myPlugin = function() {
    
        // 没有必要再作 $(this) ,因为"this"已经是 jQuery 对象了
        // $(this) 与 $($('#element')) 是相同的
           
        this.fadeIn('normal', function(){
            // 在这里 this 关键字指向 DOM 元素
        });                     
    };          
})( jQuery );

$('#element').myPlugin();

一个例子

(function( $ ){

  $.fn.maxHeight = function() {
  
    var max = 0;

    this.each(function() {
      max = Math.max( max, $(this).height() );
    });

    return max;
  };
})( jQuery );

var tallest = $('div').maxHeight(); // 返回最高 div 的高度

链式调用

在扩展函数的最后return this

(function( $ ){

  $.fn.lockDimensions = function( type ) {  

    return this.each(function() {

      var $this = $(this);

      if ( !type || type == 'width' ) {
        $this.width( $this.width() );
      }

      if ( !type || type == 'height' ) {
        $this.height( $this.height() );
      }

    });

  };
})( jQuery );

$('div').lockDimensions('width').css('color', 'red');

默认参数设置

除了$.extend()、也可以&&||短路操作符
$.extend(target, obj1, obj2, ...),它把多个object对象的属性合并到第一个target对象中,遇到同名属性,总是使用靠后的对象的值,也就是越往后优先级越高。

(function( $ ){

  $.fn.tooltip = function( options ) {  

    //默认参数可以写在外面
    var settings = $.extend( {
      'location' : 'top',
      'background-color' : 'blue'
    }, options);

    return this.each(function() {

    });

  };
})( jQuery );

$('div').tooltip({
  'location' : 'left'
});    

$.fn 名称空间

(function( $ ){

  var methods = {
    init : function( options ) { 
      // 这 
    },
    show : function( ) {
      // 很
    },
    hide : function( ) { 
      // 好
    },
    update : function( content ) { 
      // !!! 
    }
  };

  $.fn.tooltip = function( method ) {
    
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    
  
  };

})( jQuery );

// 调用  init 方法
$('div').tooltip(); 

// 调用  init 方法
$('div').tooltip({
  foo : 'bar'
});

// 调用 hide 方法
$('div').tooltip('hide'); 

// 调用 update 方法
$('div').tooltip('update', 'This is the new tooltip content!');

事件,bind、unbind

bind方法支持为绑定事件定义名称空间。unbind的时候就不会影响到相同事件类型上的其它已绑定事件。

(function( $ ){

  var methods = {
     init : function( options ) {

       return this.each(function(){
         //把 reposition 方法绑定到 window 对象的 resize 事件上,名称空间为 "tooltip"。
         $(window).bind('resize.tooltip', methods.reposition);
       });

     },
     destroy : function( ) {

       return this.each(function(){
         //如果开发者想要销毁对象,可以把插件的名称空间(即 "tooltip")传给 unbind 方法,以便解除本插件对所有事件的绑定。
         //可以安全的地解除本插件的事件绑定,避免意外影响插件之外绑定的事件。
         $(window).unbind('.tooltip');
       })

     },
     reposition : function( ) { 
       // ... 
     },
     show : function( ) { 
       // ... 
     },
     hide : function( ) {
       // ... 
     },
     update : function( content ) { 
       // ...
     }
  };

  $.fn.tooltip = function( method ) {
    
    if ( methods[method] ) {
      return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    
  
  };

})( jQuery );

$('#fun').tooltip();
// Some time later...
$('#fun').tooltip('destroy');

最佳实践

  1. 总是把插件包装在闭包中 { /* plugin goes here */ })( jQuery )。
  2. 不在插件函数的立即作用域中额外包装 this 关键字。
  3. 总是让插件函数返回 this 关键字以保持 chainability ,除非插件有真正的返回值。
  4. 不要传给插件大量参数,应该传一个可以覆盖插件默认选项的设置对象。
  5. 在单个插件中,不要让一个以上的名称空间搞乱了 jQuery.fn 对象。
  6. 总是为方法、事件和数据定义名称空间。

其它 $.fn.extend

(function($){
     $.fn.extend({         
         changeStyle: function(option){             
           var defaultSetting = { colorStr:"green",fontSize:12};
           var setting = $.extend(defaultSetting,option);
           this.css("color",setting.colorStr).css("fontSize",setting.fontSize+"px");        
           return this; 
          }
     });
}(jQuery));

$.extend方法和$.fn.extend方法都可以用来扩展jQuery功能,通过阅读jQuery源码我们可以发现这两个方法的本质区别,那就是$.extend方法是在jQuery全局对象上扩展方法,$.fn.extend方法是在$选择符选择的jQuery对象上扩展方法。所以扩展jQuery的公共方法一般用$.extend方法,定义插件一般用$.fn.extend方法。

jQuery插件集

针对特定元素的扩展filter

$.fn.external = function () {
    // return返回的each()返回结果,支持链式调用:
    return this.filter('a').each(function () {
        // 注意: each()内部的回调函数的this绑定为DOM本身!
        var a = $(this);
        var url = a.attr('href');
        if (url && (url.indexOf('http://')===0 || url.indexOf('https://')===0)) {
            a.attr('href', '#0')
             .removeAttr('target')
             .append(' <i class="uk-icon-external-link"></i>')
             .click(function () {
                if(confirm('你确定要前往' + url + '?')) {
                    window.open(url);
                }
            });
        }
    });
}

$('#main').external();
$('#main a').external();

jQuery.extend({...});静态方法

typeof jQuery==>"function"

jQuery.fn.extend({...});jQuery原型上的方法

jQuery.fn=jQuery.prototype

jQuery.extend({...})是给function jQuery添加静态属性或方法
jQuery().extend({...})是给jQuery对象添加属性或方法


额外:

扩展类方法:
jQuery.extend({
    fn1: function(){console.log('gyh')}
});
$.fn1(); // gyh
或者:
jQuery.fn2 = function(){console.log('gyh2')}
$.fn2();// gyh2

扩展实例方法(原型上的方法)
jQuery.fn.extend({
    fn1: function(){console.log(this)}
});
$('body').fn1(); // [body.library.Chrome, prevObject: init(1), context: document, selector: "body"]
或者:
jQuery.fn.fn2 = function(){console.log(this)}
$('head').fn2(); // [head, prevObject: init(1), context: document, selector: "head"]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容

  • 1.JQuery 基础 改变web开发人员创造搞交互性界面的方式。设计者无需花费时间纠缠JS复杂的高级特性。 1....
    LaBaby_阅读 1,167评论 0 1
  • 1.JQuery 基础 改变web开发人员创造搞交互性界面的方式。设计者无需花费时间纠缠JS复杂的高级特性。 1....
    LaBaby_阅读 1,330评论 0 2
  • 在线阅读 http://interview.poetries.top[http://interview.poetr...
    程序员poetry阅读 114,315评论 24 450
  • 吃货,大概就是午睡起来,发现很饿,恰好中午揉的面已经醒好,于是果断请了半个小时假,在家蒸馒头。 胖子是一个对于食物...
    胖鱼_2282阅读 666评论 8 5
  • 今日是颓废的自己与内心的一场自我对话。 点开写作群,看到总人数变为31,心里咯噔一下,哎、怎么又少了一个? 再看看...
    小熊猫简书阅读 306评论 3 5