有时你希望在整个代码中使某项功能可用。例如,也许你想要一个可以在 jQuery 选择结果上调用的单一方法,用于对该选择执行一系列操作。在这种情况下,你可能需要编写一个插件。
链接 jQuery 工作原理 101:jQuery 对象方法
在编写我们自己的插件之前,我们必须首先了解一点 jQuery 的工作原理。看看这段代码:
|
1
|
|
这是一些非常基础的 jQuery 代码,但你知道幕后发生了什么吗?每当你使用 $ 函数选择元素时,它都会返回一个 jQuery 对象。该对象包含了你一直在使用的所有方法(.css()、.click() 等)以及所有符合选择器的元素。jQuery 对象从 $.fn 对象中获取这些方法。此对象包含所有 jQuery 对象方法,如果我们想编写自己的方法,也需要将其包含在内。
链接 基础插件编写
假设我们要创建一个插件,使一组检索到的元素内的文本变为绿色。我们只需在 $.fn 中添加一个名为 greenify 的函数,它就会像任何其他 jQuery 对象方法一样可用。
|
1
2
3
4
5
|
|
请注意,要使用 .css()(另一个方法),我们使用的是 this,而不是 $( this )。这是因为我们的 greenify 函数与 .css() 属于同一个对象。
链接 链式调用
这虽然可行,但为了让我们的插件在实际环境中生存,还需要做几件事。jQuery 的特性之一是链式调用,即你可以将五六个动作链接到一个选择器上。这是通过让所有 jQuery 对象方法再次返回原始 jQuery 对象来实现的(有少数例外:不带参数调用的 .width() 返回所选元素的宽度,且不可链式调用)。让我们的插件方法支持链式调用只需要一行代码:
|
1
2
3
4
5
6
|
|
链接 保护 $ 别名和添加作用域
$ 变量在 JavaScript 库中非常流行,如果你在 jQuery 中使用另一个库,则必须使用 jQuery.noConflict() 使 jQuery 不使用 $。然而,这将破坏我们的插件,因为它是在假设 $ 是 jQuery 函数别名的前提下编写的。为了与其他插件良好运行,并且 仍能使用 jQuery 的 $ 别名,我们需要将所有代码放在一个立即调用函数表达式 (IIFE)中,然后将 jQuery 传入该函数,并将参数命名为 $:
|
1
2
3
4
5
6
7
8
|
|
此外,立即调用函数的主要目的是让我们拥有自己的私有变量。假设我们想要一种不同的绿色,并想将其存储在一个变量中:
|
1
2
3
4
5
6
7
8
9
10
|
|
链接 最小化插件占用空间
编写插件时,好的做法是在 $.fn 中只占用一个位置。这既降低了你的插件被覆盖的可能性,也降低了你的插件覆盖其他插件的可能性。换句话说,这样做是不好的:
|
1
2
3
4
5
6
7
8
9
10
11
|
|
更好的做法是只占用一个位置,并使用参数来控制该位置执行的操作。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
|
链接 使用 each() 方法
典型的 jQuery 对象将包含对任意数量 DOM 元素的引用,这就是为什么 jQuery 对象通常被称为集合的原因。如果你想对特定元素进行任何操作(例如获取 data 属性、计算特定位置),那么你需要使用 .each() 来循环遍历这些元素。
|
1
2
3
4
5
6
7
|
|
注意,我们返回的是 .each() 的结果而不是返回 this。由于 .each() 本身已经是可链式调用的,它会返回 this,然后由我们返回。这比我们目前一直在做的方法能更好地维持链式调用。
链接 接收选项
随着你的插件变得越来越复杂,通过接收选项来使插件可定制是一个好主意。最简单的方法(尤其是选项很多时)是使用对象字面量。让我们修改 greenify 插件以接收一些选项。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
|
用法示例:
|
1
2
3
|
|
color 的默认值 #556b2f 被 $.extend() 覆盖为橙色。
链接 综合应用
以下是一个使用了我们讨论过的某些技术的小型插件示例:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
|
这个方便的插件会遍历集合中的所有锚点(anchor),并在括号中追加 href 属性。
|
1
2
3
4
5
|
|
不过我们的插件还可以进行优化:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
|
我们利用了 .append() 方法接收回调函数的能力,该回调函数的返回值将决定追加到集合中每个元素的内容。此外请注意,我们没有使用 .attr() 方法来获取 href 属性,因为原生 DOM API 通过同名的 href 属性为我们提供了便捷的访问方式。