本贴转自:http://www.cnblogs.com/timy/archive/2011/04/01/2001871.html,因为写的很好,所以转载了
使用 jQuery UI Widget Factory 编写有状态的插件(Stateful Plugins)
Note
这一章节的内容是基于 Scott Gonzalez 一篇博客 Building Stateful jQuery Plugins(已获作者许可)
虽然大多数的 jQuery 插件都是无状态的(stateless),也就是说, 与插件进行交互的就限于调用插件时的那一组对象, 但是有好大一部分功能需求没办法通过这种简单的插件模式来实现。
为了填补这一空白,jQuery UI 实现一套更加先进的插件系统。 它可以管理状态,允许通过一个插件暴露多个函数,并提供多个扩展点。 这套系统被称为 widget factory,对应 jQuery.widget, 也是 jQuery UI 1.8 的一部分。不过,它是可以独立于 jQuery UI 使用的。
我们接下来创建一个简单的进度条插件,用来演示 widget factory 的能力。
我们首先创建一个只能设置一次的进度条。 下面是实现代码,使用 jQuery.widget 创建一个插件。 它接受两个参数,插件名字和带有具体实现方法的对象。 当插件被调用时,它会创建一个新的插件实例,而插件方法的执行对象也就是那个实例。 这与标准 jQuery 插件实现有两点是很不一样的。一是,执行者是对象而不是 DOM 元素; 二是,执行者永远是单个对象,而不是元素集。
Example 8.3. 用 jQuery UI widget factory 创建一个简单的有状态的插件
$.widget("nmk.progressbar", {
_create: function() {
var progress = this.options.value + "%";
this.element
.addClass("progressbar")
.text(progress);
}
});
插件名字必须包含一个命名空间,这里我们用了 nmk 这个命名空间。 但这个命名空间有个限制——只允许一层,也就是说,我们不能使用像 nmk.foo 这样的命名空间。另外可以看到 widget factory 给我们提供了两个属性。一是 this.element, 它指向一个只包含一个元素的 jQuery 对象,如果插件是由包含多个元素的 jQuery 对象调用时,会给其中的每一个元素都分配一个插件实例, 并让this.element 指向它;二是 this.options, 是包含键值对形式的插件参数的 hash 对象,插件的参数就是像这样传递进来的。
Note
本例中使用了 nmk 作为命名空间。 命名空间 ui 则是保留给官方 jQuery UI 插件的。 创建自己的插件的时候,应该使用自有的命名空间的, 这样可以让人一看就清楚这插件哪来的,是否是一个大体系的一部分。
Example 8.4. 给 widget 传递参数
$("<div></div>")
.appendTo( "body" )
.progressbar({ value: 20 });
当我们调用 jQuery.widget 时,与创建标准插件的方式一样, 它也是通过往 jQuery.fn 上面添加方法的方式来扩展 jQuery 对象。 而那个方法的名称就是我们定义的插件名称除去命名空间的部分,案例中是 jQuery.fn.progressbar。调用时所传递的参数会传递给插件实例的this.options。在下面的代码中,我们可以在参数中设置一些默认值。 在设计 API 的时候,你应该先搞清楚最通常的用例,并据此设定相应的默认参数, 那么这些参数就成为可选项了。
Example 8.5. 给 widget 设置默认值
$.widget("nmk.progressbar", {
// default options
options: {
value: 0
},
_create: function() {
var progress = this.options.value + "%";
this.element
.addClass( "progressbar" )
.text( progress );
}
});
给 widget 添加方法
接下来就要初始化进度条了。我们使它可以通过调用插件实例方法的方式来执行一些操作。 要给插件定义方法,只需要将其实现代码放在定义体内即可。 我们也可以通过在方法名前加下划线的方式来定义“私有”方法。
Example 8.6. 创建 widget 的方法
$.widget("nmk.progressbar", {
options: {
value: 0
},
_create: function() {
var progress = this.options.value + "%";
this.element
.addClass("progressbar")
.text(progress);
},
// create a public method
value: function(value) {
// no value passed, act as a getter
if (value === undefined) {
return this.options.value;
// value passed, act as a setter
} else {
this.options.value = this._constrain(value);
var progress = this.options.value + "%";
this.element.text(progress);
}
},
// create a private method
_constrain: function(value) {
if (value > 100) {
value = 100;
}
if (value < 0) {
value = 0;
}
return value;
}
});
将方法名作为参数传进去即可调用插件实例的方法。 如果调用的方法需要传递参数,只需要将那些参数作为后续参数一同传递。
Example 8.7. 调用插件实例的方法
var bar = $("<div></div>")
.appendTo("body")
.progressbar({ value: 20 });
// get the current value
alert(bar.progressbar("value"));
// update the value
bar.progressbar("value", 50);
// get the current value again
alert(bar.progressbar("value"));
Note
初始化用所用的 jQuery 方法,向它传递方法名就可以执行方法,这看起来似乎很奇怪。 但这样可以在维持原来的链式调用的方式的同时,防止 jQuery 命名空间被污染。
Widget 的参数处理
有一个方法 option,是自动生成的。它可以实现在初始化过后, 对参数进行查询或设置,就像 css,attr 的用法那样,只传名字时是查询, 名字和值都有时是做设置,如果是包含键值对的 hash 对象则进行多项设置。 进行查询时,插件会返回当前该参数的值。 做设置时,插件的 _setOption 方法会被调用,修改多少个就调用多少次。 我们可以自己实现 _setOption 方法来响应这些参数的修改。
Example 8.8. 当参数被修改时执行一些操作
$.widget("nmk.progressbar", {
options: {
value: 0
},
_create: function() {
this.element.addClass("progressbar");
this._update();
},
_setOption: function(key, value) {
this.options[key] = value;
this._update();
},
_update: function() {
var progress = this.options.value + "%";
this.element.text(progress);
}
});
添加回调功能
扩展插件的一个最简单的办法就是添加回调功能, 这样使用者就可以根据插件状态的改变来采取行动。下面,我们来尝试添加一个回调功能, 在进度达到 100% 时触发。_trigger 方法介绍三个参数: 回调名称,触发回调的本地事件对象以及相关的数据。虽然其中只有回调名称是必须的, 不过其它参数对使用者来说挺有用的。比如说,创建一个可拖拽插件, 我们可以在触发回调时将原生的 mouseover 事件对象传递过去, 用户在回调函数里就可以根据这个对象中的 x/y 坐标对拖拽进行一些处理。
Example 8.9. 提供回调功能让用户进行扩展
$.widget("nmk.progressbar", {
options: {
value: 0
},
_create: function() {
this.element.addClass("progressbar");
this._update();
},
_setOption: function(key, value) {
this.options[key] = value;
this._update();
},
_update: function() {
var progress = this.options.value + "%";
this.element.text(progress);
if (this.options.value == 100) {
this._trigger("complete", null, { value: 100 });
}
}
});
回调函数实际上只是另外一种参数,因此你也可以像其它参数一样进行查询和修改了。 无论回调函数是否设置,事件都会触发的。事件类型则是由插件名称和回调名称合并而成。 回调和事件被触发时会收到同样的两个参数:事件对象和相关数据。可以看下面的例子。
如果你的插件提供些功能是允许用户阻止操作的,最好的方式就是提供一个可撤销的回调。 用户可以像撤销原生事件那样,调用 event.preventDefault() 或者 return false,去撤销回调和相关的事件。如果用户撤销了回调,_trigger 方法会返回 false, 在插件中就可以据此采取相应的动作。
Example 8.10. 绑定 widget 事件
var bar = $("<div></div>")
.appendTo("body")
.progressbar({
complete: function(event, data) {
alert( "Callbacks are great!" );
}
})
.bind("progressbarcomplete", function(event, data) {
alert("Events bubble and support many handlers for extreme flexibility.");
alert("The progress bar value is " + data.value);
});
bar.progressbar("option", "value", 100);
Widget Factory 背后的机制
jQuery.widget 被调用时,它会为你的插件创建一个构造函数, 并以插件定义体作为其 prototype。所有默认提供的方法来自于一个基础的 widget prototype, 定义在 jQuery.Widget.prototype。当插件实例化时, 它会被用jQuery.data 的方式保存在原来的 DOM 元素里, 以插件名作为 key 值。
因为插件实例时直接绑定到 DOM 元素,你甚至可以直接访问到插件实例而不用 绕经那些暴露出来的插件方法。这样你就可以不用传方法名的方式而是直接去调用实例方法, 实例的属性也可以直接访问了。
var bar = $("<div></div>")
.appendTo("body")
.progressbar()
.data("progressbar" );
// call a method directly on the plugin instance
bar.option("value", 50);
// access properties on the plugin instance
alert(bar.options.value);
使用构造函数和 prototype 的方式来实现插件的一个最大的好处, 就是使扩展插件变得很简单。通过修改插件的 prototype, 可以轻松的修改所有实例的行为。比如,你要添加一个方法用于重置进度为 0%, 只要给 prototype 添加这个方法,那么所有实例上都拥有这个功能了。
$.nmk.progressbar.prototype.reset = function() {
this._setOption("value", 0);
};
清扫处理
有时候,插件让用户可以应用,然后过一阵再解除应用是有意义的。 这可以通过 destroy 方法的来实现。在 destroy 方法内部, 你应该取消你的插件能造成的所有修改,初始化过程中或者后面的使用中造成的。 destroy 方法在 DOM 删除时会被自动调用,所以它可以用于垃圾回收。 默认的destroy 方法会删掉 DOM 元素与插件实例直接的连接, 所以在覆盖它时是调用原先插件提供的基础 destroy 方法,是很重要的。
Example 8.11. 给 widget 添加 destroy 方法
$.widget( "nmk.progressbar", {
options: {
value: 0
},
_create: function() {
this.element.addClass("progressbar");
this._update();
},
_setOption: function(key, value) {
this.options[key] = value;
this._update();
},
_update: function() {
var progress = this.options.value + "%";
this.element.text(progress);
if (this.options.value == 100 ) {
this._trigger("complete", null, { value: 100 });
}
},
destroy: function() {
this.element
.removeClass("progressbar")
.text("");
// call the base destroy function
$.Widget.prototype.destroy.call(this);
}
});
结论
Widget factory 是创建有状态的插件的唯一途径。我们有不同的插件模型可供选用, 各有优缺。Widget factory 解决了大量基础性问题,有助于提高效率,有利于代码重用, 非常适合用来创建 jQuery UI 和其它有状态的插件。
分享到:
相关推荐
“jQuery UI Cookbook” provides you with practical recipes featuring in-depth coverage of every widget in the framework, including how to address limitations that impact your everyday development ...
1. **Widget Factory**: jQuery UI 的基础是 Widget Factory,这是一个用于创建可重用组件的框架。它规范了组件的创建过程,使得组件具有统一的行为和生命周期管理。 2. **交互(Interactions)**: 包括如拖放...
- **Widget Factory**: jQuery UI 的基础是Widget Factory,这是一个用于构建自定义UI组件的框架,它确保组件遵循一致的API和生命周期方法,如`_create()`, `_destroy()`, `option()`, 和 `disable()`等。...
4. **Widget Factory**:jQuery UI的组件都是基于Widget Factory构建的,这是一个强大的抽象层,使得创建和扩展组件变得简单。 5. **Interactions**:这些是处理用户交互的组件,如Draggable(可拖动)、Resizable...
1. **Widget Factory**: jQuery UI的核心是Widget Factory,它是一种用于创建自定义UI组件的机制。通过这个工厂,开发者可以方便地创建具有统一API和行为的UI元素。 2. **Interactions(交互)**: 包括拖放...
- **Widget Factory**:jQuery UI的核心机制,负责创建和管理Widgets。开发者可以通过$.widget()方法扩展新的组件。 - **Options**:每个Widget都有自己的配置选项,可以通过初始化时传递参数来设置。 - **...
而“jQuery Widget Factory”则是jQuery生态中的一个重要组成部分,它为构建可重用的、自定义的UI组件提供了便利。本篇文章将深入探讨“前端开源库-jquery-widget-compiler”,解析其核心概念、工作原理以及实际应用...
5. **实用工具**:包括 Position、Widget Factory 和 Mouse 组件,它们是其他组件的基础,提供位置计算、通用 widget 构建和鼠标事件处理等功能。 下载的 "jquery-ui-1.10.1.custom" 文件应该是 jQuery UI 的特定...
4. **Utilities(实用工具)**:除了小部件和特效,jQuery UI还提供了诸如Position、TABBING、Widget Factory等实用工具函数,帮助开发者处理位置计算、元素对齐、事件管理等问题。 **jQuery UI与Ajax框架组件的...
同时,jQuery UI还提供了一种叫做"widget factory"的机制,让创建自定义组件变得更加简单和标准化。 总结来说,"jquery-ui-1.8.5"是Web开发者构建高效、美观UI的强大工具。通过理解和使用这个压缩包中的资源,...
Widget工厂(widget factory)是jQuery UI提供的一种机制,它允许开发者定义自己的自定义组件,并确保这些组件符合统一的API标准。通过调用$.widget()函数,我们可以创建一个新的widget,传入组件名、基础类(通常是...
4. **Utilities**:包括Position(定位)、Widget Factory(组件工厂)等工具函数,方便开发者在实现自定义功能时调用。 5. **Examples**:这是最核心的部分,包含了各种组件的使用示例代码。通过这些代码,开发者...
- **Widget Factory**:通过$.widget方法创建自定义组件,遵循一定的结构和规范。 - **主要组件**:包括Accordion(折叠面板)、Dialog(对话框)、DatePicker(日期选择器)、Slider(滑块)、Tabs(选项卡)等。...
1. **Widget Factory**:jQuery UI的核心是Widget Factory,它提供了一种统一的方式来创建可复用、可配置的组件,确保了代码的规范性和一致性。 2. **交互组件**:包括拖放(Draggable)、可叠放(Droppable)、可排序...
8. **性能优化**:在大型应用中,为了提高性能,可以使用“懒加载”策略,只在需要时初始化组件,或者利用 jQuery UI 的“widget factory”来减少代码体积。 9. **自定义构建**:根据项目需求,可以从 jQuery UI 的...
2. **Widget Factory**: jQuery UI 的基础是Widget Factory,这是一个用于创建可重用组件的框架。所有的jQuery UI组件都是基于此工厂构建,确保了组件的一致性和可扩展性。 3. **特效**: 包括动画、过渡效果等,如...
- **Widget Factory**: jQuery UI 的核心是 Widget Factory,它是一个强大的机制,用于创建可复用、可配置且具有完整生命周期的 UI 组件。开发者可以通过这个工厂轻松地创建自定义组件。 - **主题**: jQuery UI ...
- **Widget Factory**:jQuery UI 的核心是 Widget Factory,它提供了一种统一的方式来创建可重用的组件,确保了代码的模块化和一致性。 - **Theming**:jQuery UI 1.10 继续支持其著名的 ThemeRoller 工具,允许...
在jQuery UI 1.8.5中,最重要的组件之一是“Widget Factory”。这是一个核心机制,允许开发者将普通的DOM元素转换为具有状态、事件和配置选项的对象,从而创建自定义的UI组件。它使得组件化开发变得简单,便于维护和...
9. **Widget Factory**:jQuery UI 提供了一个Widget Factory,它是一个用于创建自定义组件的框架,使得开发者可以按照统一的模式构建自己的UI组件。 在使用jQuery UI时,需要注意的是,由于它包含了大量的...