65.9K
CodeProject 正在变化。 阅读更多。
Home

简单的 jQuery 插件详解

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (35投票s)

2013年7月24日

CPOL

8分钟阅读

viewsIcon

61919

downloadIcon

568

理解简单的 jQuery 插件。

引言

jQuery 是 Web 开发中最流行的 JavaScript 库。如果您对 jQuery 有一定的了解,您可能熟悉这样的代码:

$("#someId").text("Something");
$("someTagName").hide();

这里 text()hide() 是内置的 jQuery 函数。我们将尝试创建一个可以调用我们自己定义的函数来使用 jQuery 做一些很酷的事情。这种写法看起来就像普通的 jQuery 语句一样。例如:

$("someTagName").myFunction(options) ;

这里 myFunction() 是一个用户定义的函数。

这些用户定义的函数打包在一起就称为 jQuery 插件。在开发 Web 项目时,我们经常需要创建自己的 jQuery 插件。本教程将帮助您理解如何按照广为人知​​的标准创建基本的 jQuery 插件。

先决条件

在开始创建插件之前,我们需要了解一些主题。

  1. 函数声明和函数表达式。 
  2. 立即调用的函数表达式
  3. jQuery 的无冲突模式

让我们逐一了解。

在任何 JavaScript 文件中,如果您写下类似这样的代码:

justFunction();
 
//function declaration    
function justFunction() 
{ 
    alert("something");
}

这将调用 justFunction() 并显示一个警报。这样定义函数称为函数声明。

现在还有另一种定义函数的方式:

var anotherFunction = function() { alert ("something")}

现在,如果您写下类似这样的代码:

anotherFunction(); 
 
// Function Expression 
var anotherFunction = function() { alert ("something"); }

尽管 anotherFunction 在这里是一个函数,但在控制台中会报错。这称为函数表达式。

原因在于函数声明在任何代码执行之前加载。而函数表达式仅在解释器到达该代码行时才加载。因此,如果您尝试在函数表达式加载之前调用它,您将收到错误。

但是,如果您调用函数声明,它将始终有效。因为在所有声明加载之前,没有任何代码可以被调用。所以您必须始终在函数表达式定义后调用它。

// Function Expression 
var anotherFunction = function() { alert ("something"); } 
anotherFunction();

现在,可以通过在匿名函数后添加括号来立即调用函数表达式,如下所示:

var anotherFunction = function() { alert ("something"); }(); //paranthesis added

此代码片段和上面的代码执行相同的操作(显示警报)。现在 anotherFunction 变量与上面不同,因为它现在被赋值为匿名函数将返回的值。目前它没有返回任何东西,所以 anotherFunction  是未定义的。所以,如果您写下类似这样的代码:

var anotherFunction = function() { alert ("something"); }();
anotherFunction(); //error

这将导致错误,因为匿名函数不返回任何函数。如果它返回类似这样的内容:

var anotherFunction = 
  function() { alert ("something"); return "some string"; }(); //returns string

anotherFunction 现在是一个字符串变量。而如果

var anotherFunction = function() { alert ("something"); return function(){
        alert("somethingElse")
        }; }();  // returns function

现在 anotherFunction 是一个函数,可以像 anotherFunction() 一样调用。

您可以向此函数表达式传递参数,例如:

var anotherFunction = function(p1,p2) { console.log(p1); 
        console.log(p2); }(param1,param2 ); //param1,param2 are parameters

函数表达式和函数声明之间的主要区别之一是:函数表达式可以使用括号(调用)立即调用,而函数声明则不能。

现在,如果我们不想将函数表达式赋值给变量,那么我们必须将其写在括号内:

(function() { alert ("something");});

要调用它,我们需要在末尾再添加一组括号,例如:

(function() { alert ("something"); }());

与之前一样,我们也可以向其传递参数,例如:

( function(param){ console.log(param); }(param));

这类函数称为 **IIFE**(立即调用的函数表达式)。

**IIFE** 只是一个匿名函数(没有名称与之关联),它被包装在一对括号内并立即调用。

( function(){ }());

讨论这个的原因是,我们所有的插件代码都将包含在 **IIFE** 中。要理解为什么这样做,我们需要理解另一个主题:jQuery 的无冲突模式。

jQuery 有一个 jQuery 对象的简写方式,即 $ 符号。许多 JavaScript 库像 jQuery 一样使用 $ 作为函数或变量名。如果您需要将另一个 JavaScript 库与 jQuery 一起使用,您可以将 jQuery 的默认 $ 符号替换为任何其他名称。如果您像这样在 HTML 页面的头部包含 jQuery 文件:

<head>
    <script src="jquery-1.7.1.js" type="text/javascript"></script>
    <script src="index.js" type="text/javascript"></script>
</head>

index.js 文件在 jQuery 文件之后立即加载。因此,您可以使用此代码更改 '$' 符号:

var jq = jQuery.noConflict(); 
 
//In all other codes you have to use the 'jq' to access the jquery codes  instead of the 
//default '$' sign, like document load event below 

jq(function()
{
// Do something with jquery
jq("div p").hide();
}
);

这样,jQuery 的 $ 符号与其他 JavaScript 库的 $ 符号之间就不会发生冲突。

更改 jQuery 的默认 $ 对许多软件开发者来说可能不是一件令人高兴的事,因为他们已经非常习惯于使用 $ 符号编写 jQuery 代码。对此有一个解决方案。如果您不需要混合 jQuery 和其他 JavaScript 库的代码,那么您可以将所有 jQuery 代码包装在 **IIFE**(立即调用的函数表达式)中。因为我们的插件仅依赖于 jQuery,所以我们所有的插件代码都将包含在此代码块中。

(function ($) 
{ 
} (jQuery));

在这里,我们将 jQuery 对象作为参数传递,并使用 $ 符号接收它。因此,所有代码都在局部作用域内,并且不会与其他库的 $ 符号冲突。使用 IIFE 的好处不仅仅是局部作用域。 这里有一篇很好的文章。现在我们已经准备好创建我们的 jQuery 插件。在下一节中,我们将创建自己的插件。

创建 jQuery 插件

对于这个简短的教程,我们需要四个文件:

  1. index.html
  2. index.js
  3. jquery.myPlugin.js
  4. jquery-1.7.1.js

index.html 文件中,写一些简单的 HTML 代码,如下所示:

<html>
<head>
 
    <title>Index</title>
    <script src="jquery-1.7.1.js" type="text/javascript"></script>
    <script src="index.js" type="text/javascript"></script>
    <script src="jquery.myPlugin.js" type="text/javascript"></script>
</head>
 
<body>
 
    <h1>First Header</h1>
    <h1>Second Header</h1> 
    <h1>Third Header</h1>
 
    <input id="btnChange" type="button" value="Change" />
</body>
</html>

jquery.myPlugin.js 是我们将编写所有 jQuery 插件代码的文件。好了,让我们做一些简单的事情,比如将标题的颜色更改为红色。所以我们的插件代码看起来会像这样:

(function($){
        
    $.fn.makeChange = function(){
        this.css({color : "red"});
    };

}(jQuery));

index.js 文件中,在表单加载事件内,我们绑定 change 按钮的点击事件并调用我们的 makeChamge 插件函数。

$(function(){
    
    $("#btnChange").click(function(){
        
            $("h1").makeChange();
    });
});

如果我们现在双击 index.html 文件,浏览器中的页面将显示如下:

现在,如果您单击“更改”按钮,它将显示如下:

是的,这意味着我们的插件代码正在工作。现在让我们再看一下插件代码:

(function($){
        
    $.fn.makeChange = function(){
        this.css({color : "red"});
    };
 
}(jQuery));

您可以看到我们已将 makeChange 函数赋值给 $.fn

$.fn 指向 jQuery.prototype。您添加到其中的任何方法或属性都将可用于所有 jQuery 包装对象的实例。请注意,要使用 .css(),我们使用 this,而不是 $( this )。这是因为我们的 makeChange 函数与 .css() 属于同一对象。

现在,让我们添加更多功能,例如更改文本和字体样式。

(function($){
    
    $.fn.makeChange = function(){
    this.css({color : "red",fontStyle: "italic"});
    this.text("Header Text Changed");
};

}(jQuery));

现在,如果您再次加载页面并单击“更改”按钮,您将看到类似这样的内容:

现在,jQuery 支持一种称为链式操作的技术,该技术允许我们在同一元素上连续运行多个 jQuery 命令。这样的语句是链式操作的示例:

$("#someId").css("color","red").slideUp(2000).slideDown(2000);

因为我们正在创建一个 jQuery 插件,所以我们的 makeChange 函数应该支持链式操作。

让我们在 index.js 文件中尝试一个链式语句:

$("h1").makeChange().slideUp(2000);

现在,让我们重新加载 index.html 页面并单击“更改”按钮:

正如我们的链式语句所表明的,标题应该向上滑动并变得不可见,但这并没有发生。所以我们的 makeChange 函数不支持链式操作。要使其支持链式操作,我们需要返回元素,如下所示:

(function($){
        
    $.fn.makeChange = function(){
        this.css({color : "red",fontStyle: "italic"});
        this.text("Header Text Changed");
        
        return this;
    };
 
}(jQuery));

现在,如果您重新加载 index.html 页面并再次单击“更改”按钮,您将看到标题以您给定的速度(此处为 2000 毫秒)向上滑动。最终它们会消失。

现在我们已经为我们的插件添加了链式操作功能。

现在,让我们尝试分别获取每个标题的文本并对其进行编辑。所以这简单的代码应该可以做到:

(function($){
        
    $.fn.makeChange = function(){
        
        var hText= this.text(); //get the element text 
        
        this.css({color : "red",fontStyle: "italic"});
        this.text(hText+" With New Added Text");
        
        return this;
    };
 
}(jQuery));

现在,在重新加载 index.html 页面并单击“更改”按钮后,我们将看到类似这样的内容:

这不符合我们的目的,因为我们希望标题文本为“First Header With New Added Text”。

这里发生的是 this.text() 函数返回了所有 3 个标题的文本。现在要解决这个问题,我们需要使用 jQuery 的 each 迭代器。

(function($){
        
    $.fn.makeChange = function(){
        
        return this.each( function(){
            
            var hText= $(this).text();
            $(this).css({color : "red",fontStyle: "italic"});
            $(this).text(hText+" With New Added Text");
        });
    };

}(jQuery));

现在,重新加载 index.html 页面并单击“更改”按钮将得到:

使用 each 循环非常重要,因为我们典型的 jQuery 对象将包含对任意数量 DOM 元素的引用。如果您想操作特定元素,则必须需要 each 循环。

请注意,each 函数中的 this 元素现在是一个 jQuery 包装的元素,因为函数上下文已更改。我们在这里将元素包装了三次。最好的做法是将 this 元素包装起来并将其赋值给一个变量,然后重复使用它。

(function($){
        
    $.fn.makeChange = function(){
        
        return this.each( function(){
            
            var self= $(this);
            
            var hText= self.text();
            self.css({color : "red",fontStyle: "italic"});
            self.text(hText+" With New Added Text");
        });
    };
 
}(jQuery));

到目前为止,我们的 jQuery 插件会对元素执行一些静态更改。现在,让我们给用户提供传递参数的机会。这意味着,让我们接受一些选项。

index.js 文件中,您可以这样提供选项:

$(function(){
    
    $("#btnChange").click(function(){
        
           $("h1").makeChange({color: "green", 
                               text: "Text Supplied By Option" , 
                               fontStyle: "italic"
            });
    });
});

而在 jquery.myPlugin.js 中,您可以这样接受和使用选项:

(function($){
        
    $.fn.makeChange = function(options){
        
        return this.each( function(){
            
            var self= $(this);
            
            var hText= self.text();
            self.css({color : options.color,fontStyle: options.fontStyle});
            self.text(hText+" "+ options.text );
        });
    };
 
}(jQuery));

现在,如果您重新加载 index.html 页面并单击“更改”按钮,您将看到:

现在,如果未提供值,我们的插件应该有一些默认设置。如果提供了值,则默认值将被覆盖。为此,我们可以使用 $.extend 方法。现在我们看一下代码:

(function($){

    $.fn.makeChange = function(options){
        
		var defaults = {
				 text: "Default Text",
				 color: null,
				 fontStyle: null
			        };
					   
		var settings = $.extend(defaults, options);
		
        return this.each( function(){
            
            var self= $(this);
            
            var hText= self.text();
			
            self.css({color : settings.color,fontStyle: settings.fontStyle});
            self.text(hText+" "+ settings.text );
        });
    };
 
}(jQuery));

这里我们有一个 defaults 变量,其中包含我们的默认设置。options 包含用户定义的设置。

$.extend 方法将两个或多个对象的内容合并到第一个对象中。因此,settings 变量包含插件的整体设置。

另一件重要的事情是 colorfontStyle 的默认值为 null。因此,在执行任何修改之前最好检查是否向选项传递了值。所以我们的插件代码看起来像这样:

function($){

    $.fn.makeChange = function(options){
        
		var defaults = {
				  text: "Default Text",
				  color: null,
				  fontStyle: null
			       };
					   
		var settings = $.extend(defaults, options);
		
        return this.each( function(){
            
            var self= $(this);
            
            var hText= self.text();
	self.text(hText+" "+ settings.text );
			
			if(settings.color) //check if a value is passed or not
			{
				self.css({color : settings.color});
			}
			
			if(settings.fontStyle)
			{
				self.css({fontStyle: settings.fontStyle});
			}
		});
    };
 
}(jQuery));

最后,我们也可以在选项中传递函数。所以,在 index.js 页面,您可以这样发送您的函数:

$(function(){
    
    $("#btnChange").click(function(){
        
        $("h1").makeChange({color: "green",
                text: "Text Supplied By Option",
                fontStyle: "italic",
                complete: function(){
                    alert("Done");
                }
            });
    });
});

这里 complete 是您提供给选项的一个函数。现在在我们的插件代码中,我们需要像这样调用这个函数:

(function($){
        
    $.fn.makeChange = function(options){
        
        var defaults = {
                         text: "Default Text",
                         color: null,
                         fontStyle: null
                       };
                       
        var settings = $.extend(defaults, options);
        
        return this.each( function(){
            
            var self= $(this);
            
            var hText= self.text();
            self.text(hText+" "+ settings.text );
            
            if(settings.color)
            {
                self.css({color : settings.color});
            }
            
            if(settings.fontStyle)
            {
                self.css({fontStyle: settings.fontStyle});
            }
            
            if($.isFunction( settings.complete )) //check if its a function
            {
                settings.complete.call(this);
            }
        });
    };
}(jQuery));

这里我们首先检查 settings.complete 是否已提供并且它是一个函数,然后才调用它。

因此,如果您重新加载 index.html 并单击“更改”按钮,我们将为三个标题收到三个警报。

这就是本文的全部内容。希望对您有所帮助。

© . All rights reserved.