简单的 jQuery 插件详解






4.94/5 (35投票s)
理解简单的 jQuery 插件。
引言
jQuery 是 Web 开发中最流行的 JavaScript 库。如果您对 jQuery 有一定的了解,您可能熟悉这样的代码:
$("#someId").text("Something");
$("someTagName").hide();
这里 text()
和 hide()
是内置的 jQuery 函数。我们将尝试创建一个可以调用我们自己定义的函数来使用 jQuery 做一些很酷的事情。这种写法看起来就像普通的 jQuery 语句一样。例如:
$("someTagName").myFunction(options) ;
这里 myFunction()
是一个用户定义的函数。
这些用户定义的函数打包在一起就称为 jQuery 插件。在开发 Web 项目时,我们经常需要创建自己的 jQuery 插件。本教程将帮助您理解如何按照广为人知的标准创建基本的 jQuery 插件。
先决条件
在开始创建插件之前,我们需要了解一些主题。
- 函数声明和函数表达式。
- 立即调用的函数表达式
- 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 插件
对于这个简短的教程,我们需要四个文件:
- index.html
- index.js
- jquery.myPlugin.js
- 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
变量包含插件的整体设置。
另一件重要的事情是 color
和 fontStyle
的默认值为 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 并单击“更改”按钮,我们将为三个标题收到三个警报。
这就是本文的全部内容。希望对您有所帮助。