jQuery UI 的部件工厂使得构建扩展现有部件功能的部件变得容易。这样做可以让你在现有基础上构建强大的部件,也可以对现有部件的功能进行微调。
注意:本文假设你对部件工厂是什么以及它如何工作有一些基本了解。如果你不熟悉这一点,请先阅读如何使用部件工厂。
链接 创建部件扩展
使用部件工厂创建部件是通过将部件名称和原型对象传递给 $.widget() 来完成的。以下代码在 "custom" 命名空间中创建了一个 "superDialog" 部件。
|
1
|
|
为了允许扩展,$.widget() 可选地接受一个部件的构造函数作为父级。当指定父部件时,将其作为第二个参数传递——在部件名称之后,在部件原型对象之前。
与上一个示例一样,以下代码也在 "custom" 命名空间中创建了一个 "superDialog" 部件。然而,这次传递了 jQuery UI 对话框部件($.ui.dialog)的构造函数,表明 superDialog 部件应该使用 jQuery UI 的对话框部件作为父级。
|
1
|
|
在这里,superDialog 和 dialog 本质上是具有不同名称和命名空间的等效部件。为了使我们的新部件更有趣,我们可以向其原型对象添加方法。
部件的原型对象是传递给 $.widget() 的最后一个参数。到目前为止,我们的示例一直使用空对象。让我们向该对象添加一个方法
|
1
2
3
4
5
6
7
8
9
10
|
|
现在 superDialog 有一个 red() 方法,它会将其文本颜色更改为红色。请注意部件工厂如何自动将 this 设置为部件的实例对象。有关实例上可用方法和属性的完整列表,请参阅部件工厂的 API 文档。
链接 扩展现有方法
有时你需要调整或添加到现有部件方法的行为。为此,请在原型对象上指定一个与要覆盖的方法同名的方法。以下示例覆盖了对话框的 open() 方法。由于对话框默认会自动打开,因此当此代码运行时,将记录 "open"。
|
1
2
3
4
5
6
7
8
|
|
虽然它运行了,但有一个问题。由于我们覆盖了 open() 的默认行为,对话框不再显示在屏幕上。
当我们将方法放在原型对象上时,我们实际上并没有覆盖原始方法——相反,我们将一个新方法放置在原型链中更高的位置。
为了使父级的方法可用,部件工厂提供了两种方法——_super() 和 _superApply()。
链接 使用 _super() 和 _superApply() 访问父级
_super() 和 _superApply() 调用父部件中同名的方法。请参考以下示例。与上一个示例一样,此示例也覆盖了 open() 方法以记录 "open"。然而,这次运行 _super() 来调用对话框的 open() 并打开对话框。
|
1
2
3
4
5
6
7
8
9
10
|
|
_super() 和 _superApply() 被设计成与原生 Function.prototype.call() 和 Function.prototype.apply() 方法的行为相似。因此,_super() 接受一个参数列表,而 _superApply() 接受一个参数数组。这种差异在下面的示例中显示。
|
1
2
3
4
5
6
7
8
9
|
|
链接 重新定义部件
jQuery UI 1.9 增加了部件重新定义自身的能力。因此,我们可以将现有部件的名称和构造函数传递给 $.widget(),而不是创建新部件。以下示例在 open() 中添加了相同的日志记录,但没有创建新部件来完成此操作。
|
1
2
3
4
5
6
7
8
|
|
使用这种方法,您可以扩展现有部件的方法,并且仍然可以使用 _super() 访问原始方法——所有这些都无需创建新部件。
链接 部件与多态性
在与部件扩展及其插件交互时,有一点需要注意。父部件的插件不能用于在作为子部件的元素上调用方法。这在下面的示例中显示。
|
1
2
3
4
5
6
7
8
9
|
|
上面,父部件的插件 dialog() 不能在作为 superDialog 的元素上调用 close() 方法。有关调用部件方法的更多信息,请参阅部件方法调用。
链接 自定义单个实例
到目前为止,我们看到的所有示例都扩展了部件原型上的方法。在原型上覆盖的方法会影响部件的所有实例。
为了说明这一点,请参考下面的示例;对话框的两个实例都使用相同的 open() 方法。
|
1
2
3
4
5
6
7
8
9
10
|
|
虽然这很强大,但有时你只需要更改部件单个实例的行为。为此,请获取实例的引用并使用正常的 JavaScript 属性赋值来覆盖方法。下面的示例显示了这一点。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
|
这种为单个实例覆盖方法的技术非常适合一次性定制。