jQuery插件开发 总结

一般来说,jQuery插件的开发分为两种:一种是挂在jQuery命名空间下的全局函数,也可称为静态方法;另一种是jQuery对象级别的方法,即挂在jQuery原型下的方法,这样通过选择器获取的jQuery对象实例也能共享该方法。

一、在讲解jQuery插件基本结构和模式前,先介绍下两个重要的方法:

1、$.extend(target, [object1], [objectN])

该方法主要用于合并两个或更多对象的内容(属性)到第一个对象,并返回合并后的第一对象。如果该方法只有一个参数target,则该参数将扩展jQuery的命名空间,即作为静态方法挂在jQuery全局对象下,如jQuery里的$.ajax、$.getJSON全局函数等:

// 将hello方法挂在jQuery全局对象下,作为静态方法
$.extend({
    hello: function() {alert("hello");}
});

又如,在jQuery全局对象中扩展一个snsgou命名空间:

$.extend({ snsgou: { } });

并将hello方法扩展到之前扩展的JQuery的snsgou命名空间中去:

$.extend($.snsgou, {
    hello: function() {alert("hello");}
});

在开发插件时,也可以将方法扩展到jQuery的原型中去,如:

$.extend($.fn, {
    hello: function() {alert("hello");}
});

值得注意的是:多个对象参数合并时,会破坏第一个对象的结构,所以可传递一个空对象作为第一个参数,如:$.extend({}, object1, object2);

另外,对于深度拷贝,即如果对象中也嵌套子对象,则会拷贝并覆盖子对象(如果有同名属性)全部的属性,需要设置第一个参数deep为true值,如:$.extend(true, target, object1, [objectN])。

2、$.fn.extend(target)

在jQuery中,$.fn本质上是等于jQuery的原型,即$.fn = $.prototype, 所以该方法实际上是为jQuery原型添加方法,即把target对象的方法添加到jQuery原型中去,这样jQuery对象实例就可以访问添加的方法了,这也是jQuery插件开发常用的方法,特别是添加多个接口时。如:

// 将hello、hello2方法添加到jquery原型中
$.fn.extend({
    hello: function() {alert("hello!");},
    hello2: function() {alert("hello again!);}
});

如果添加单个方法到jQuery原型中,可使用$.fn.pluginName方法添加,如:

// 将hello方法添加到jquery原型中
$.fn.hello = function() {
    // ...
};

二、在开发过一些 jQuery 插件后,慢慢的探索出了一套开发jQuery插件的基本结构和模式。这样在面对复杂多变的需要方案时,只要专注最主要的逻辑代码就行了。另外,使用相同的设计模式和架构也让修复bug或者二次开发更容易。

在这里分享一些平时遇到和总结的经验:

1、把全部代码放在闭包(一个即时执行函数)里

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

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

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

var jQ = function($) {
  // code goes here
};
jQ(jQuery);

2、提供插件的默认参数选项

一个扩展性良好的插件应该是可以让使用者根据需求自定义参数选项,并控制插件的行为,所以提供恢复默认选项是很有必要的。你可以通过jQuery的extend方法来设置这些选项:

var defaults = {
    name: "snsgou",
    age: 22,
    job: "student",
    walk: function() {
        // ...
    }
};

$.extend({}, defaults, options || {});

注:参数选项设置时也可以使用如下模式,即把参数对象挂在插件命名空间下:

$.fn.pluginName.defaults = {
    name: "snsgou",
    age: 22,
    job: "student",
    walk: function() {
        // ...
    }
};

3、遍历多个元素并返回

jQuery使用Sizzle选择器引擎,Sizzle可以为你的函数提供多元素操作(例如对所有类名相同的元素)。这是jQuery几个优秀的特性之一,在开发插件过程中即使你不准备为你的插件提供多元素支持,但为这做准备仍然是一个很好的实践。另外,jQuery有一个很好的特点就是可以进行方法级联,也可称为链式调用,所以我们不应该破坏这个特性,始终在方法中返回一个元素。如:

function($) {
    // 参数选项设置...
    // 向jQuery原型中添加你的插件代码,用“pluginName”作为插件的函数名称。
    $.fn.pluginName = function(options) {
        // 遍历匹配的元素||元素集合,并返回this,以便进行链式调用。
        return this.each(function() {
            // 此处可通过this来获得每个单独的元素(jQuery对象)
            var _this = $(this);

        });
    };
})(jQuery);

4. 一次性代码放在主循环以外

这一条很重要,但是常常被忽略。简单的讲,如果你有一段代码是一堆默认值,只需要被实例化一次,而不是每次调用你插件功能的时候都需要实例化,你应该把这段代码放在插件方法的外面。这样可以让你的插件运行的更高效,节省内存。如:

function($) {
    // 参数选项设置
    var defaults = {
        name: "snsgou",
        age: 22,
        job: "student",
        walk: function() {
            // ...
        }
    };
    // 向jQuery原型中添加你的插件代码,用“pluginName”作为插件的函数名称。
    $.fn.pluginName = function(options) {
        var opts = $.extend({}, defaults, options || {});

        // 遍历匹配的元素||元素集合,并返回this,以便进行链式调用。
        return this.each(function() {
            // 此处可通过this来获得每个单独的元素(jQuery对象)
            var _this = $(this);
           // ...
        });
    };
})(jQuery);

5、定义公有方法和私有方法

一般情况下,对于一个jQuery插件,一个基本的函数就可以很好地工作,但是对于复杂一点的插件就需要提供各种各样的方法和私有函数。你可能会使用不同的命名空间去为你的插件提供各种方法,但是添加过多的命名空间反而会使代码变得混乱,健壮性下降。所以最好的解决办法是适当地定义私有函数和方法。例子如下所示:

(function($) {
    // 在我们插件容器内,定义一个私有方法
    var privateFunction = function() {
        // code here
    };

    // 通过字面量创造一个对象,存储我们需要的公有方法
    var methods = {
        // 在字面量对象中定义每个单独的方法
        init: function() {
            // 为了更好的灵活性,对来自主函数,并进入每个方法中的选择器其中的每个单独的元素都执行代码
            return this.each(function() {
                // 为每个独立的元素创建一个jQuery对象
                var _this = $(this);
                // 执行代码 例如:privateFunction()
            });
        },
        destroy: function() {
            // 对选择器每个元素都执行方法
            return this.each(function() {
                // 执行代码
            });
        }
    };

    $.fn.pluginName = function() {
        // 获取我们的方法,遗憾的是,如果我们用function(method){}来实现,这样会毁掉一切的
        var method = arguments[0];

        // 检验方法是否存在
        if(methods[method]) {
            // 如果方法存在,存储起来以便使用
            // 注意:我这样做是为了等下更方便地使用each()
            method = methods[method];

        // 如果方法不存在,检验对象是否为一个对象(JSON对象)或者method方法没有被传入
        } else if (typeof method === "object" || !method ) {
            // 如果我们传入的是一个对象参数,或者根本没有参数,init方法会被调用
            method = methods.init;

        } else {
            // 如果方法不存在或者参数没传入,则报出错误。需要调用的方法没有被正确调用
            $.error("Method" +  method + "does not exist on jQuery.pluginName");
            return this;
        }

        // 调用我们选中的方法
        // 再一次注意我们是如何将each()从这里转移到每个单独的方法上的
        return method.call(this);
    };

})(jQuery);

注意我把 privateFunction 当做了一个函数内部的全局变量。考虑到所有的代码的运行都是在插件容器内进行的,所以这种做法是可以被接受的,因为它只在插件的作用域中可用。在插件中的主函数(pluginName)中,我检验了传入参数所指向的方法是否存在。如果方法不存在或者传入的是参数为对象, init 方法会被运行。最后,如果传入的参数不是一个对象而是一个不存在的方法,我们会报出一个错误信息。

下面是一些用法的例子

// 为每个类名为 ".className" 的元素执行init方法
$(".className").pluginName();
$(".className").pluginName("init");
$(".className").pluginName("init", {}); // 向init方法传入“{}”对象作为函数参数
$(".className").pluginName({}); // 向init方法传入“{}”对象作为函数参数

// 为每个类名为 “.className” 的元素执行destroy方法
$(".className").pluginName("destroy");
$(".className").pluginName("destroy", {}); // 向destroy方法传入“{}”对象作为函数参数

// 所有代码都可以正常运行
$(".className").pluginName("init", "argument1", "argument2"); // 把 "argument1" 和 "argument2" 传入 "init"

// 不正确的使用
$(".className").pluginName("nonexistantMethod");
$(".className").pluginName("nonexistantMethod", {});
$(".className").pluginName("argument1"); // 会尝试调用 "argument1" 方法
$(".className").pluginName("argument1", "argument2"); // 会尝试调用 "argument1" ,“argument2”方法
$(".className").pluginName("privateFunction"); // "privateFunction" 不是一个方法

6、添加持久性数据

在插件开发过程中,有时需要在插件中保存设置和信息,这时jQuery中的$.data函数就可以派上用场了。使用时,它会尝试获取和元素相关的数据,如果数据不存在,它就会创造相应的数据并添加到元素上。一旦你使用了$.data来为元素添加信息,请确认你已经记住remember,当不再需要数据的时候,用$.removeData函数来删除相应的数据。

(function($) {
    var privateFunction = function() {
        // 执行代码
    }

    var methods = {
        init: function(options) {

            // 在每个元素上执行方法
            return this.each(function() {
                var _this = $(this);

                // 尝试去获取settings,如果不存在,则返回“undefined”
                var settings = _this.data("pluginName");

                // 如果获取settings失败,则根据options和default创建它
                if (typeof settings === "undefined") {

                    var defaults = {
                        propertyName: "value",
                        onSomeEvent: function() {}
                    };

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

                    // 保存我们新创建的settings
                    _this.data("pluginName", settings);
                } else {
                    / 如果我们获取了settings,则将它和options进行合并(这不是必须的,你可以选择不这样做)
                    settings = $.extend({}, settings, options);

                    // 如果你想每次都保存options,可以添加下面代码:
                    // _this.data("pluginName", settings);
                }

                // 执行代码

            });
        },
        destroy: function(options) {
            // 在每个元素中执行代码
            return $(this).each(function() {
                var _this = $(this);

                // 执行代码

                // 删除元素对应的数据
                _this.removeData("pluginName");
            });
        },
        val: function(options) {
            // 这里的代码通过.eq(0)来获取选择器中的第一个元素的,我们或获取它的HTML内容作为我们的返回值
            var someValue = this.eq(0).html();

            // 返回值
            return someValue;
        }
    };

    $.fn.pluginName = function() {
        var method = arguments[0];

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

        return method.apply(this, arguments);

    }

})(jQuery);

在上面的代码中,首先检验元素的数据是否存在。如果数据不存在,“options”和“default”会被合并,构建成一个新的settings,然后用$.data()保存在元素中。

参考:http://www.cnblogs.com/%86%e5%bc%80%e5%8f%91.html

时间: 2024-10-11 12:26:42

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插件开发模式 软件开发过程中是需要一定的设计模式来指导开发的,有了模式,我们就能更好地组织我们的代码,并且从这些前人总结出来的模式中学到很多好的实践. jQuery插件开发方式主要有三种: 通过$.extend()来扩展jQuery 通过$.fn 向jQuery添加新的方法 通过$.widget()应用jQuery UI的部件工厂方式创建 通常我们使用第二种方法来进行简单插件开发,说简单是相对于第三种方式.第三种方式是用来开发更高级jQuery部件的,该模式开发出来的部件带有很多jQ

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