发布在:插件

如何创建基本插件

有时,您希望在整个代码中提供某个功能。例如,您可能希望在 jQuery 选择上调用一个方法,该方法对选择执行一系列操作。在这种情况下,您可能希望编写一个插件。

link jQuery 工作原理 101:jQuery 对象方法

在我们编写自己的插件之前,我们必须首先了解 jQuery 的工作原理。看看这段代码

1
$( "a" ).css( "color", "red" );

这是一些非常基本的 jQuery 代码,但您知道幕后发生了什么吗?每当您使用 $ 函数选择元素时,它都会返回一个 jQuery 对象。此对象包含您一直在使用的所有方法(.css().click() 等)以及符合您选择器的所有元素。jQuery 对象从 $.fn 对象获取这些方法。此对象包含所有 jQuery 对象方法,如果我们想要编写自己的方法,它也需要包含这些方法。

link 基本插件创作

假设我们想要创建一个插件,使检索到的元素集合中的文本变为绿色。我们所要做的就是向 $.fn 添加一个名为 greenify 的函数,它将像任何其他 jQuery 对象方法一样可用。

1
2
3
4
5
$.fn.greenify = function() {
this.css( "color", "green" );
};
$( "a" ).greenify(); // Makes all the links green.

请注意,要使用另一个方法 .css(),我们使用 this,而不是 $( this )。这是因为我们的 greenify 函数是与 .css() 相同对象的一部分。

链接 链式操作

此方法有效,但我们需要做一些事情才能使我们的插件在现实世界中生存。jQuery 的一项功能是链式操作,当您将五个或六个操作链接到一个选择器上时。这是通过让所有 jQuery 对象方法再次返回原始 jQuery 对象来实现的(有一些例外:在没有参数的情况下调用的 .width() 返回所选元素的宽度,并且不可链式操作)。使我们的插件方法可链式操作需要一行代码

1
2
3
4
5
6
$.fn.greenify = function() {
this.css( "color", "green" );
return this;
}
$( "a" ).greenify().addClass( "greenified" );

链接 保护 $ 别名并添加范围

$ 变量在 JavaScript 库中非常流行,如果您将另一个库与 jQuery 一起使用,则必须使 jQuery 不使用 $jQuery.noConflict()。但是,这会破坏我们的插件,因为它是在假设 $jQuery 函数别名的前提下编写的。为了与其他插件配合良好,并且仍然使用 jQuery $ 别名,我们需要将我们所有的代码放入 立即调用的函数表达式 中,然后将函数 jQuery 传递给它,并将参数命名为 $

1
2
3
4
5
6
7
8
(function ( $ ) {
$.fn.greenify = function() {
this.css( "color", "green" );
return this;
};
}( jQuery ));

此外,立即调用的函数的主要目的是允许我们拥有自己的私有变量。假设我们想要不同的绿色,并且我们想将其存储在变量中。

1
2
3
4
5
6
7
8
9
10
(function ( $ ) {
var shade = "#556b2f";
$.fn.greenify = function() {
this.css( "color", shade );
return this;
};
}( jQuery ));

链接 最小化插件占用空间

在编写插件时,只在 $.fn 中占用一个插槽是一个好习惯。这既减少了插件被覆盖的可能性,也减少了插件覆盖其他插件的可能性。换句话说,这是不好的

1
2
3
4
5
6
7
8
9
10
11
(function( $ ) {
$.fn.openPopup = function() {
// Open popup code.
};
$.fn.closePopup = function() {
// Close popup code.
};
}( jQuery ));

最好有一个插槽,并使用参数来控制该插槽执行的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(function( $ ) {
$.fn.popup = function( action ) {
if ( action === "open") {
// Open popup code.
}
if ( action === "close" ) {
// Close popup code.
}
};
}( jQuery ));

链接 使用 each() 方法

您典型的 jQuery 对象将包含对任意数量的 DOM 元素的引用,这就是为什么 jQuery 对象通常被称为集合。如果您想对特定元素进行任何操作(例如获取数据属性、计算特定位置),则需要使用 .each() 来循环遍历元素。

1
2
3
4
5
6
7
$.fn.myNewPlugin = function() {
return this.each(function() {
// Do something to each element here.
});
};

请注意,我们返回 .each() 的结果,而不是返回 this。由于 .each() 本身就是可链式操作的,因此它返回 this,然后我们返回 this。这是一种比我们迄今为止所做的更好的保持可链式操作的方法。

链接 接受选项

随着插件变得越来越复杂,通过接受选项来使插件可定制是一个好主意。最简单的方法,尤其是在有很多选项的情况下,是使用对象字面量。让我们更改我们的 greenify 插件以接受一些选项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(function ( $ ) {
$.fn.greenify = function( options ) {
// This is the easiest way to have default options.
var settings = $.extend({
// These are the defaults.
color: "#556b2f",
backgroundColor: "white"
}, options );
// Greenify the collection based on the settings variable.
return this.css({
color: settings.color,
backgroundColor: settings.backgroundColor
});
};
}( jQuery ));

示例用法

1
2
3
$( "div" ).greenify({
color: "orange"
});

color 的默认值 #556b2f$.extend() 覆盖为橙色。

链接 将其组合在一起

下面是一个使用我们讨论过的一些技术的小插件示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(function( $ ) {
$.fn.showLinkLocation = function() {
this.filter( "a" ).each(function() {
var link = $( this );
link.append( " (" + link.attr( "href" ) + ")" );
});
return this;
};
}( jQuery ));
// Usage example:
$( "a" ).showLinkLocation();

这个方便的插件遍历集合中的所有锚点,并在括号中附加 href 属性。

1
2
3
4
5
<!-- Before plugin is called: -->
<a href="page.html">Foo</a>
<!-- After plugin is called: -->
<a href="page.html">Foo (page.html)</a>

不过,我们可以优化我们的插件

1
2
3
4
5
6
7
8
9
10
11
12
13
(function( $ ) {
$.fn.showLinkLocation = function() {
this.filter( "a" ).append(function() {
return " (" + this.href + ")";
});
return this;
};
}( jQuery ));

我们正在使用 .append() 方法接受回调的能力,并且该回调的返回值将决定附加到集合中每个元素的内容。还要注意,我们没有使用 .attr() 方法来检索 href 属性,因为本机 DOM API 通过恰当命名的 href 属性为我们提供了轻松的访问。