jQuery 插件开发

jQuery插件开发模式

软件开发过程中是需要一定的设计模式来指导开发的,有了模式,我们就能更好地组织我们的代码,并且从这些前人总结出来的模式中学到很多好的实践。

jQuery插件开发方式主要有三种:

  1. 通过$.extend()来扩展jQuery
  2. 通过$.fn 向jQuery添加新的方法
  3. 通过$.widget()应用jQuery UI的部件工厂方式创建

通常我们使用第二种方法来进行简单插件开发,说简单是相对于第三种方式。第三种方式是用来开发更高级jQuery部件的,该模式开发出来的部件带有很多jQuery内建的特性,比如插件的状态信息自动保存,各种关于插件的常用方法等,非常贴心,这里不细说...。

而第一种方式又太简单,仅仅是在jQuery命名空间或者理解成jQuery身上添加了一个静态方法而以。所以我们调用通过$.extend()添加的函数时直接通过$符号调用($.myfunction())而不需要选中DOM元素($(‘#example‘).myfunction())。请看下面的例子。

$.extend({
    sayHello: function(name) {
        console.log(‘Hello,‘ + (name ? name : ‘World‘) + ‘!‘);
    }
})
$.sayHello(); //调用
$.sayHello(‘zhangsan‘); //带参调用  

运行结果:

上面代码中,通过$.extend()向jQuery添加了一个sayHello函数,然后通过$直接调用。到此你可以认为我们已经完成了一个简单的jQuery插件了。

但如你所见,这种方式用来定义一些辅助方法是比较方便的。比如一个自定义的console,输出特定格式的信息,定义一次后可以通过jQuery在程序中任何需要的地方调用它。

$.extend({
    log: function(message) {
        var now = new Date(),
            y = now.getFullYear(),
            m = now.getMonth() + 1, //!JavaScript中月分是从0开始的
            d = now.getDate(),
            h = now.getHours(),
            min = now.getMinutes(),
            s = now.getSeconds(),
            time = y + ‘/‘ + m + ‘/‘ + d + ‘ ‘ + h + ‘:‘ + min + ‘:‘ + s;
        console.log(time + ‘ My App: ‘ + message);
    }
})
$.log(‘initializing...‘); //调用  

上面直接在方法中传递的匿名对象,但是如果方法很多的话,不便于管理。也可以为这种静态方法提供命名空间,如下:

$.YG = {
        log: function(message) {
            var now = new Date(),
                y = now.getFullYear(),
                m = now.getMonth() + 1, //!JavaScript中月分是从0开始的
                d = now.getDate(),
                h = now.getHours(),
                min = now.getMinutes(),
                s = now.getSeconds(),
                time = y + ‘/‘ + m + ‘/‘ + d + ‘ ‘ + h + ‘:‘ + min + ‘:‘ + s;
            console.log(time + ‘ My App: ‘ + message);
        },
        hello:function(name){
            alert(‘Hello,‘ + (name?name:‘world!‘));
        }
    };
    $.YG.log(‘initializing...‘); //调用
    $.YG.hello(‘zhangsan‘);  

但这种方式无法利用jQuery强大的选择器带来的便利,要处理DOM元素以及将插件更好地运用于所选择的元素身上,还是需要使用第二种开发方式。你所见到或使用的插件也大多是通过此种方式开发。

插件开发

下面我们就来看第二种方式的jQuery插件开发。

基本方法

先看一下它的基本格式:

$.fn.pluginName = function() {
    //在这里放入你要运行的代码
}  

基本上就是往$.fn上面添加一个方法,名字是我们的插件名称。然后我们的插件代码在这个方法里面展开。

比如我们将页面上所有链接颜色转成红色,则可以这样写这个插件:

$.fn.myPlugin = function() {
    //在这里面,this指的是用jQuery选中的元素
    //example :$(‘a‘),则this=$(‘a‘)
    this.css(‘color‘, ‘red‘);
}  

来看一下完整的例子:

HTML

<ul>
    <li><a href="http://www.sina.com.cn">新浪</a></li>
    <li><a href="http://www.baidu.com">百度</a></li>
    <li><a href="http://www.163.com">网易</a></li>
    <li><a href="http://www.qq.com.cn">QQ</a></li>
</ul>
    <input type="button" value="点击" id="myBtn">

JS

$.fn.changeColor = function(color){
    color = color || ‘red‘
    this.css(‘color‘, color);
}

$(function(){
    $(‘#myBtn‘).click(function(){
        $(‘li a‘).changeColor()
    });
});

在插件名字定义的这个函数内部,this指代的是我们在调用该插件时,用jQuery选择器选中的元素,一般是一个jQuery类型的集合。比如$(‘a‘)返回的是页面上所有a标签的集合,且这个集合已经是jQuery包装类型了,也就是说,在对其进行操作的时候可以直接调用jQuery的其他方法而不需要再用美元符号来包装一下。

所以在上面插件代码中,我们在this身上调用jQuery的css()方法,也就相当于在调用 $(‘a‘).css()。

理解this在这个地方的含义很重要。这样你才知道为什么可以直接商用jQuery方法同时在其他地方this指代不同时我们又需要用jQuery重新包装才能调用,下面会讲到。初学容易被this的值整晕,但理解了就不难。

将上面的示例代码稍微做一下修改,点击按钮之后,将a标签中href属性内容放入到界面显示,HTML代码不变,将js稍微做修改:

JS

$.fn.changeColor = function(color){
        color = color || ‘red‘
        this.css(‘color‘, color);
        this.each(function(){
            $(this).append(‘==>‘ + $(this).attr(‘href‘));
        });
    }

    $(function(){
        $(‘#myBtn‘).click(function(){
            $(‘li a‘).changeColor()
        });
    });  

支持链式调用

jQuery最大的特性就是支持链式调用,但是用了上面的方式后,如果代码中调用自定的jQuery插件方法,你会发现不支持链式调用了,如下面代码:

$(function(){
    $(‘#myBtn‘).click(function(){
        $(‘li a‘).changeColor().css(‘border‘,‘1px solid #ccc‘);
    });
});  

这里的代码在执行完自己的插件方法之后,再调用了css方法继续修改,但是界面报错。

其实原因很简单,就是链式调用其实不断的返回了jquery DOM元素,让后面的连缀知道前面的对象是谁,但是这里却没有这么做,修改的方式也很简单,在自定的插件中,返回jquery DOM元素即可:

$.fn.changeColor = function(color){
    color = color || ‘red‘
    this.css(‘color‘, color);
    return this.each(function(){
        $(this).append(‘==>‘ + $(this).attr(‘href‘));
    });
    //在这里返回this也是一样
    //return this
}

$(function(){
    $(‘#myBtn‘).click(function(){
        $(‘li a‘).changeColor().css(‘border‘,‘1px solid #ccc‘);
    });
});  

让插件接收参数

一个强劲的插件是可以让使用者随意定制的,这要求我们提供在编写插件时就要考虑得全面些,尽量提供合适的参数。

比如现在我们不想让链接只变成红色,我们让插件的使用者自己定义显示什么颜色,要做到这一点很方便,只需要使用者在调用的时候传入一个参数即可。同时我们在插件的代码里面接收。另一方面,为了灵活,使用者可以不传递参数,插件里面会给出参数的默认值。

在处理插件参数的接收上,通常使用jQuery的extend方法,上面也提到过,但那是给extend方法传递单个对象的情况下,这个对象会合并到jQuery身上,所以我们就可以在jQuery身上调用新合并对象里包含的方法了,像上面的例子。当给extend方法传递一个以上的参数时,它会将所有参数对象合并到第一个里。同时,如果对象中有同名属性时,合并的时候后面的会覆盖前面的。

利用这一点,我们可以在插件里定义一个保存插件参数默认值的对象,同时将接收来的参数对象合并到默认对象上,最后就实现了用户指定了值的参数使用指定的值,未指定的参数使用插件默认值。

为了演示方便,再指定一个参数fontSize,允许调用插件的时候设置字体大小。

$.fn.changeColor = function(params){

    //设置的是默认对象
    var defaults = {
        color:‘red‘,
        fontSize:‘12px‘
    };

    //首先遵循默认对象返回,然后再按照第二参数params返回
    var settings = $.extend(defaults,params);

    this.css({
        ‘color‘:settings.color,
        ‘fontSize‘:settings.fontSize
    });

    return this;
}

$(function(){
    $(‘#myBtn‘).click(function(){
        // $(‘li a‘).changeColor();
        // 注意如果要传参数需要传递对象,因为在插件中是用对象接受的值
        //$(‘li a‘).changeColor({‘color‘:‘yellow‘});
        $(‘li a‘).changeColor({
            ‘color‘:‘yellow‘,
            ‘fontSize‘:‘20px‘
        });
    });
});  

保护好默认参数

注意到上面代码调用extend时会将defaults的值改变,这样不好,因为它作为插件因有的一些东西应该维持原样,另外就是如果你在后续代码中还要使用这些默认值的话,当你再次访问它时它已经被用户传进来的参数更改了。

通过图上可以看到,执行了var settings = $.extend(defaults,params);这句代码之后,defaults的值就被改变了,那如果在之后再用到defaults变量的话,值就已经被改变了,看下面的代码:

$.fn.changeColor = function(params){

    //设置的是默认对象
    var defaults = {
        color:‘red‘,
        fontSize:‘12px‘
    };

    //首先遵循默认对象返回,然后再按照第二参数params返回
    var settings = $.extend(defaults,params);

    this.css({
        ‘color‘:settings.color,
        ‘fontSize‘:settings.fontSize
    });
    //加入了下面这一句代码
    this.css({
        ‘color‘:defaults.color,
    });
    return this;
}

$(function(){
    $(‘#myBtn‘).click(function(){
        $(‘li a‘).changeColor({
            ‘color‘:‘yellow‘,
            ‘fontSize‘:‘20px‘
        });
    });
});

在原来代码的基础上,就加上了注释后的代码。想要达到的效果就是通过上面一句改变color和fontSize。然后再通过defaults的值改变回来。那么这个时候会发现不能改回defaults原来的值。

一个好的做法是将一个新的空对象做为$.extend的第一个参数,defaults和用户传递的参数对象紧随其后,这样做的好处是所有值被合并到这个空对象上,保护了插件里面的默认值。只需要改变一句代码:

var settings = $.extend({},defaults,params);//将一个空对象做为第一个参数

到此,插件可以接收和处理参数后,就可以编写出更健壮而灵活的插件了。若要编写一个复杂的插件,代码量会很大,如何组织代码就成了一个需要面临的问题,没有一个好的方式来组织这些代码,整体感觉会杂乱无章,同时也不好维护,所以将插件的所有方法属性包装到一个对象上,用面向对象的思维来进行开发,无疑会使工作轻松很多。

面向对象的插件开发

为什么要有面向对象的思维,因为如果不这样,你可能需要一个方法的时候就去定义一个function,当需要另外一个方法的时候,再去随便定义一个function,同样,需要一个变量的时候,毫无规则地定义一些散落在代码各处的变量。

还是老问题,不方便维护,也不够清晰。当然,这些问题在代码规模较小时是体现不出来的。

如果将需要的重要变量定义到对象的属性上,函数变成对象的方法,当我们需要的时候通过对象来获取,一来方便管理,二来不会影响外部命名空间,因为所有这些变量名还有方法名都是在对象内部。

将上面的代码做一下面向对象的修改,你会发现代码也会整洁美观很多。不过面向对象的思维需要转变大家的思维模式。不再是需要什么,想起什么再造什么,而是需要整体上的一个规划。

首先,之前的代码无非就是在$.fn.changeColor这个函数里面做了很多操作。那么我们先把这些操作提取出来,把这些操作放在一个对象中,通过对象帮助我们完成。就像把一件事情交给其他人去做一样的道理。比如这个人(对象)就叫Beautifier,它有自己的一些属性和方法,我们只需要调用Beautifierbeautify()方法就能帮我们完成之前的操作。所以,先根据这个理念。我们修改之前的代码

$.fn.changeColor = function(params){
    var beautifier = new Beautifier()
    beautifier.beautify()
}  

首先能想到的就是这种代码,Beautifier对象里面的细节先不用讨论。

1.这里如果想要实现以后的链式操作,那么beautify()函数就应该返回当前对象this,所以beautify()函数首先应该有返回值
2.在new Beautifier()对象的时候,应该想到,我们要操作具体的DOM对象,以及传进来的参数params所以,我们这个需要构造函数,根据上面这两点,将上面的代码修改一下。

$.fn.changeColor = function(params){
    //构造函数传递是当前对象jquery DOM,以及外面传递的参数params
    var beautifier = new Beautifier(this,params)
    //返回值,为了以后便于链式操作
    return beautifier.beautify()
}  

那么现在来构建Beautifier函数。

function Beautifier(elem,params){
    this.$elem = elem;
    this.defaults = {
        color:‘red‘,
        fontSize:‘12px‘,
        border:‘1px solid #ccc‘
    };
    this.settings = $.extend({},this.defaults,params);
}

Beautifier.prototype = {
    constructor : Beautifier,
    beautify : function(){
        this.$elem.css({
            color:this.settings.color,
            fontSize:this.settings.fontSize,
            border:this.settings.border
        });
        return this.$elem;
    }
}  

将代码全部组合起来:

function Beautifier(elem,params){
    this.$elem = elem;
    this.defaults = {
        color:‘red‘,
        fontSize:‘12px‘,
        border:‘1px solid #ccc‘
    };
    this.settings = $.extend({},this.defaults,params);
}

Beautifier.prototype = {
    constructor : Beautifier,
    beautify : function(){
        this.$elem.css({
            color:this.settings.color,
            fontSize:this.settings.fontSize,
            border:this.settings.border
        });
        return this.$elem;
    }
}

$.fn.changeColor = function(params){
    var beautifier = new Beautifier(this,params);
    return beautifier.beautify();
}

$(function(){
    $(‘#myBtn‘).click(function(){
        $(‘li a‘).changeColor({
            ‘color‘:‘yellow‘,
            ‘fontSize‘:‘20px‘
        });
    });
});  

可以看到这里的代码层次明显要清晰了很多。希望大家逐渐掌握面向对象的编程方式。

使用闭包

把全部代码放在闭包(一个即时执行函数)里。此时闭包相当于一个私有作用域,外部无法访问到内部的信息,并且不会存在全局变量的污染情况。官方创建开发规范的解释是:
a) 避免全局依赖;
b) 避免第三方破坏;
c) 兼容jQuery操作符‘$‘和‘jQuery ‘。
如下所示:

(function($) {
    // 局部作用域中使用$来引用jQuery
    // ...
})(jQuery);  

这段代码在被解析时可理解成以下代码:

var jQ = function($) {
  // 你要在这里编写的代码
};
jQ(jQuery);  

所以上面的整个代码,都可以包含在这个闭包范围内:

;(function($){
    function Beautifier(elem,params){
        this.$elem = elem;
        this.defaults = {
            color:‘red‘,
            fontSize:‘12px‘,
            border:‘1px solid #ccc‘
        };

        this.settings = $.extend({},this.defaults,params);

    }

    Beautifier.prototype = {
        constructor : Beautifier,
        beautify : function(){
            this.$elem.css({
                color:this.settings.color,
                fontSize:this.settings.fontSize,
                border:this.settings.border
            });
            return this.$elem;
        }
    }

    $.fn.changeColor = function(params){
        var beautifier = new Beautifier(this,params);
        return beautifier.beautify();
    }
})(jQuery)

$(function(){
    $(‘#myBtn‘).click(function(){
        $(‘li a‘).changeColor({
            ‘color‘:‘yellow‘,
            ‘fontSize‘:‘20px‘
        });
    });

});  

这里注意在前面不要忘记加上;,主要是为了闭包函数和之前的函数区分开,避免冲突。举个简单的例子:

var foo=function(){
    //别人的代码
}//注意这里没有用分号结尾

//开始我们的代码。。。
;(function(){
    //我们的代码。。
    alert(‘Hello!‘);
})();  

可以自己去做一下试验,如果没有之前的 ; 这段代码就会报错。所以注意在代码前加上。

当然既然可以传递jQuery,那么我们想在外部传入的参数,都可以传入,如:

;(function($,window,document,undefined){
    //我们的代码。。
    //blah blah blah...
})(jQuery,window,document);  

当我们这样做之后,window等系统变量在插件内部就有了一个局部的引用,可以提高访问速度,会有些许性能的提升。

而至于这个undefined,稍微有意思一点,为了得到没有被修改的undefined,我们并没有传递这个参数,但却在接收时接收了它,因为实际并没有传,所以‘undefined’那个位置接收到的就是真实的‘undefined‘了。是不是有点hack的味道,值得细细体会的技术,当然不是我发明的,都是从前人的经验中学习。

时间: 2024-10-04 15:39:37

jQuery 插件开发的相关文章

掌握jQuery插件开发

在实际开发工作中,总会碰到像滚动,分页,日历等展示效果的业务需求,对于接触过jQuery以及熟悉jQuery使用的人来说,首先想到的肯定是寻找现有的jQuery插件来满足相应的展示需求.目前页面中常用的一些组件,都有多种jQuery插件可供选择,网络上也有很多专门收集jQuery插件的网站.利用jQuery插件确实可以给我们的开发工作带来便捷,但是如果只是会简单使用,而对其中的原理不甚了解,那么在使用过程中碰到问题或者对插件进行定制开发时就会有诸多疑惑.本文的目的就是可以快速了解jQuery插件

jQuery插件开发(一):jQuery类方法

一.jQuery插件开发的方法 jQuery插件的编写方法主要有两种: 1.基于jQuery对象的插件 2.基于jQuery类的插件 二.基于jQuery类的插件 1.什么是jQuery类的插件? jQuery类方法其实就是jquery全局函数,即jquery对象的方法,实际上就是位于jquery命名空间的内部函数.这些函数有一个特征就是不操作DOM元素,而是操作 Javascript非元素对象.直观的理解就是给jquery类添加类方法,可以理解为添加静态方法 2.给jQuery类添加方法. /

jQuery插件开发精品教程(让你的jQuery更上一个台阶)

刘哇勇的部落格要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样,得平台者得天下.苹果,微软,谷歌等巨头,都有各自的平台及生态圈. 学会使用jQuery并不难,因为它简单易学,并且相信你接触jQuery后肯定也使用或熟悉了不少其插件.如果要将能力上升一个台阶,编写一个属于自己的插件是个不错的选择. 本教程可能不是最精品的,但一定是最细致的. jQuery插件开发模式 软件开发过程中是需要一定的设计模式来指导开发

JQuery插件开发精品教程,让你的jQuery提升一个台阶

本文转载自 http://www.cnblogs.com/Wayou/p/jquery_plugin_tutorial.html 要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样,得平台者得天下.苹果,微软,谷歌等巨头,都有各自的平台及生态圈. 学会使用jQuery并不难,因为它简单易学,并且相信你接触jQuery后肯定也使用或熟悉了不少其插件.如果要将能力上升一个台阶,编写一个属于自己的插件是个不错的选择.

jQuery插件开发模式

http://www.cnblogs.com/gavin-num1/p/5655126.html jQuery插件开发模式 软件开发过程中是需要一定的设计模式来指导开发的,有了模式,我们就能更好地组织我们的代码,并且从这些前人总结出来的模式中学到很多好的实践. 根据<jQuery高级编程>的描述,jQuery插件开发方式主要有三种: 通过$.extend()来扩展jQuery 通过$.fn 向jQuery添加新的方法 通过$.widget()应用jQuery UI的部件工厂方式创建 通常我们使

jQuery插件开发前准备

[前言] 关于jQuery的插件,网上一搜一大把,一开始在项目中使用别人写的插件的时候,真是佩服的五体投地,调用的时候简简单单的几句代码,就能实现很复杂的功能.那么如何开发自己的插件呢?其实并不难,从简单的开始,一步一步网上添加功能,最后咋们也能写出功能强大的插件. [jQuery插件开发模式] jQuery插件开发模式有三种: (1)通过$.extend()来扩展jQuery 多用于拓展工具方法,比如给一个数组封装一个方法,功能是将其中的重复元素删除:$.removeSameItem([1,1

jQuery插件开发---转载

要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样,得平台者得天下.苹果,微软,谷歌等巨头,都有各自的平台及生态圈. 学会使用jQuery并不难,因为它简单易学,并且相信你接触jQuery后肯定也使用或熟悉了不少其插件.如果要将能力上升一个台阶,编写一个属于自己的插件是个不错的选择. 本教程可能不是最精品的,但一定是最细致的. jQuery插件开发模式 软件开发过程中是需要一定的设计模式来指导开发的,有了模式,

跟我一起学JQuery插件开发

http://www.cnblogs.com/Leo_wl/archive/2012/04/06/2435511.html 以前一直比较好奇,jquery插件是怎么开发的,怎么写属于自己的插件? 昨天在逛codeproject网站的时候,突然看到一篇文章:How to write plugin in Jquery. 如果对E文好的同学 ,可以看上面的连接. 现在我把上面网站的及结合自己的想法写这篇文章.希望能得到大牛们的支持和谅解...大鸟飞过...欢迎拍装. 资料来源: [1]How to w

jQuery 插件开发——PopupLayer(弹出层)

导读:上次写了一篇关于GridView的插件开发方法,上几天由于工作需要,花了一天左右的事件封装了popupLayer(弹出层)插件.今天有时间就记录一下自己的开发思想与大家分享下,同时也算是对这段时间的工作概要吧. 就我在开发过程中的理解和开发的经验,一般常用的弹出层有三类(其实还有一类就是弹出可以输入内容的,但是这种可以被替代,所以就特别拿出来写了):Confirm.Alert.LoadContent(url).其中Alert又可以分成五种(当然也可以是四种),分别是: "error&quo