首先,我们要创建一个progress bar,它只允许我们简单的设置进度值。正如我们接下来将要看到的,我们需要通过调用 jQuery.widget 及其两个参数来实现这一操作,这两个参数分别是:将要创建的插件的名称,以及一个包含该插件所支持方法的对象字面量(object literal)。

当我们的插件被调用时,它将创建一个新的插件实例,并且包含在该实例上下文(context)中的方法都会被执行。这与标准的jQuery插件有两个主要的区别。首先,上下文 (context)是一个对象,而不是DOM元素。其次,上下文(context)始终都是一个单独的对象,而不是集合。

使用 jQuery UI 部件工厂创建一个简单的,带状态的插件:

 $.widget( "nmk.progressbar", {

     _create: function() {
var progress = this.options.value + "%";
this.element.addClass( "progressbar" ).text( progress );
} });

插件的名称必须包含一个命名空间(namespace);在我们的例子当中使用 nmk 作为命名空间(namespace)。关于命名空间(namespace)这里有一个限制,就是它只能够拥有一个层级;换句话说,我们不能使用类似 nmk.foo 这样的形式来作为命名空间(namespace)。同时我们看到部件工厂已经为我们提供了两个属性。第一个属性是 this.element ,它是一个只包含一个元素的jQuery对象。如果调用插件的jQuery对象包含多个元素,那么每一个元素将分别拥有一个插件实例,并且每一个插件实例都拥有自己的 this.element 属性。第二个属性是 this.options ,该属性是一个散列,包含有与我们插件选项相对应的所有键/值配对。

将选项传递给部件:

 $( "<div />" ).appendTo( "body" ).progressbar({ value: 20 });

当我们调用 jQuery.widget 时,它通过向 jQuery.fn 添加一个方法来扩展jQuery(也是我们创建标准插件的方式)。被添加的方法的名称基于你在调用 jQuery.widget 时所使用的名称,不包含命名空间(namespace)。在我们的例子当中,它将创建 jQuery.fn.progressbar。传递给插件的选项在插件实例内部已经在 this.options 中进行了设置。

正如接下来我们将要展示的,我们可以为任何选项指定一个默认值。当设计API时,你应当想好该插件最常见的使用情形,以便可以设置合适的默认值,并使所有的选项都是完全可选的。

为部件设置默认选项值:

 $.widget( "nmk.progressbar", {

     // Default options.
options: {
value: 0
}, _create: function() {
var progress = this.options.value + "%";
this.element.addClass( "progressbar" ).text( progress );
} });

为部件添加方法

现在我们可以初始化progress bar了,通过调用插件实例中的方法我们使其能够执行一些操作。要在插件中定义方法,我们只需要在传递给 jQuery.widget 的对象字面量(object literal)当中包含该方法。同时我们可以在方法名前面添加下划线(_)来使其成为私有方法。

创建部件方法:

 $.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;
} });

要在插件实例上调用方法,只需要将方法的名称传递给jQuery插件。如果所调用的是带参数的方法,只需将这些参数放置在方法名的后面。

在插件实例上调用方法:

 var bar = $( "<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" ) );

操纵部件的选项
option方法是插件中内置的方法之一。该方法允许你在初始化之后对属性进行设置。该方法的工作方式与jQuery的 .css() 和 .attr() 方法相同:你可以通过向其传递名称来将它作为getter,传递名称和值来将它作为setter,传递一个键/值配对的散列来同时设置多个值。当它被作为getter时,插件将返回与传递进来的名称相对应的选项的当前值。当它被作为setter时,每一个已经设置的选项都会调用插件的 _setOption 方法。当选项发生改变时,我们可以在插件中指定 _setOption 方法来进行反应。

当选项被设置时作出响应:

 $.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 );
} });

添加回调函数

添加回调函数让用户可以在插件状态发生变化时作出反应是扩展插件的一种简单的方式。下面我们将看到如何为progress bar添加回调函数,来表明进度何时到达百分之百。 _trigger 方法带有三个参数:回调函数的名称,原生事件对象用于触发回调函数,以及与事件有关的数据的散列。回调函数的名称是唯一必要的参数,而其他的参数在用户希望在插件上实现自己的方法时将十分有用。例如,我们编写了一个可拖动的插件,当触发拖动回调函数时,我们可以传递一个原生的鼠标移动事件,用户将可以通过这一事件对象,在 x/y 坐标的基础上对拖动作出反应。

为用户扩展提供回调函数:

 $.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 使得你可以在插件中实现合适的功能。

绑定部件事件:

 var bar = $( "<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 );

部件工厂:深入(Under the Hood)
当你调用 jQuery.widget 时,它会为你的插件创建一个构造函数(constructor),并将你传递进来的对象字面量(object literal)作为对象实例的原型(prototype)。所有自动添加到插件中的功能都来自于一个基本的部件原型(widget prototype),它被定义为 jQuery.Widget.prototype。当插件实例被创建之后,它通过 jQuery.data 将插件存储在原始的DOM元素当中,并使用插件的名称来作为键值。

由于插件实例直接与DOM元素产生联系,因此如果你愿意的话,可以直接访问插件实例而非通过插件所暴露的方法。这将允许你直接调用插件实例上的方法,而非通过将方法的名称作为字符串传递给插件,此外你还将可以直接访问插件的属性。

 var bar = $( "<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 );

插件的构造函数(constructor)和原型(prototype)所拥有的巨大好处之一就是使插件更易扩展。通过在插件原型(prototype)上添加或修改方法,我们可以改变插件所有实例的行为。例如,如果我们想要在progress bar中添加一个方法,用于重置进度为零。我们可以在插件的原型上添加这一方法,并且它立刻就可以被任意插件的实例所调用。

 $.nmk.progressbar.prototype.reset = function() {
this._setOption( "value", 0 );
};

清理

在某些情况下,允许用户随时应用和取消应用插件将十分有用。你可以通过使用 destroy 方法来达成这一目的。在 destroy 方法当中,你应当撤销插件在初始化时或之后的使用中所进行的一切动作。 destroy 方法将在被插件所关联的元素从DOM当中被移除时,自动被调用,因此这同样可以用来进行垃圾回收。默认情况下, destroy 方法会移除DOM元素和插件实例间的联系, 因此在插件的 destroy 方法中调用基类的方法十分的重要。

为部件添加 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 );
} });

总结
部件工厂是创建带状态插件的唯一方法。有少数一些不同的模型可以被使用,并且它们各有千秋。部件工厂为你解决了大部分常见的问题并且极大的提升了工作效率,它同时提升了代码的复用率,使其和其它带状态的插件一样的更加适用于jQuery UI。

原文地址:http://learn.jquery.com/plugins/stateful-plugins-with-widget-factory/

jQuery 使用 jQuery UI 部件工厂编写带状态的插件(翻译)的更多相关文章

  1. 使用 jQuery UI Widget Factory 编写有状态的插件(Stateful Plugins)

    使用 jQuery UI Widget Factory 编写有状态的插件(Stateful Plugins) Note 这一章节的内容是基于 Scott Gonzalez 一篇博客 Building ...

  2. jquery mobile扁平化设计样式--Jquery mobile Flat UI介绍

    jquery mobile扁平化设计样式--Jquery mobile Flat UI介绍 这几天开发的web app使用了jquery mobile,jquery mobile自带的样式比较适合做企 ...

  3. 基于jquery开发的UI框架整理分析

    根据调查得知,现在市场中的UI框架差不多40个左右,不知大家都习惯性的用哪个框架,现在市场中有几款UI框架稍微的成熟一些,也是大家比较喜欢的一种UI框架,那应该是jQuery,有部分UI框架都是根据j ...

  4. Jquery学习---Easy UI 框架

    Jquery的easyui 1.1. easyui的目录分析 以 jquery Easy UI 1.3.2 版本学习 demo 实例 locale 国际化信息 plugins 框架一些插件 src 源 ...

  5. 《jQuery、jQuery UI及jQuery Mobile技巧与示例》勘误收集

    此书由程学彬 (http://weibo.com/ironbin)和我合译完成,此篇博客作为勘误收集而用,若译文有误或者有任何疑问,欢迎留下评论,或者给我发邮件(地址:gzooler@gmail.co ...

  6. jQuery用面向对象的思想来编写验证表单的插件

    本人的重点是怎么构建一个简单有效可扩展的jQuery表单验证插件,这篇文章没有教你怎么用 validate plugin.我们的重点在学习一些jQuery,Javascript面向对象编程的知识. 下 ...

  7. Jquery.Treeview+Jquery UI制作Web文件预览

    效果图: 前台Html: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="D ...

  8. jQuery extend() & jQuery.fn.extend(),插件编写

    资料来源:网上资料整理并自行改编测试.复制以下代码并依赖jquery.js,jquery.validate.js即可执行.有误之处,请@我啊,敬请赐教. <!DOCTYPE html PUBLI ...

  9. jquery $与jQuery

    jquery的兼容 ie8 <script type="text/javascript" src="<%=path%>/js/jquery-3.1.1. ...

随机推荐

  1. javascript 路线整理

    前端开发很重要,编写脚本也不容易. 总结我以前的前端学习经历,基本是一团乱麻:css+javascript是在大三自学的,当时自己做课程设计,逼着自己在一个月之内,写了一个半成品的j2ee网站.当时, ...

  2. 我的第一个wp8小程序

    一:截图,功能介绍:点击音乐红色按钮,播放铃声 二:代码 XAML代码 <phone:PhoneApplicationPage x:Class="PhoneApp1.MainPage& ...

  3. dll文件已经引用,但using找不到命名空间

    一:问题截图 二:解决办法 1.没看到lz的代码中有Vancl.Server的dll. 2.确实有编译不过的问题,是Vancl.WindowsServices这个工程的target framework ...

  4. 暴力求解——UVA 572(简单的dfs)

    Description The GeoSurvComp geologic survey company is responsible for detecting underground oil dep ...

  5. 数据结构典型算法的VC实现(袁辉勇)

    1. 迷宫问题求解 #include <stdio.h> #define m 8 //迷宫内有8列 #define n 8 //迷宫内有8行 #define MAXSIZE 100//栈尺 ...

  6. warning: Could not canonicalize hostname: vpn

    warning: Could not canonicalize hostname: vpn vim /etc/hosts 127.0.0.1 hostname

  7. ssh非交互式密码输入

    ssh登陆不能在命令行中指定密码.sshpass的出现,解决了这一问题.sshpass用于非交互SSH的密码验证,一般用在sh脚本中,无须再次输入密码. 它允许你用 -p 参数指定明文密码,然后直接登 ...

  8. 面向GC的Java编程

    转自http://hellojava.info/?p=341 HelloJava微信公众账号网站 面向GC的Java编程 Leave a reply 这是内部一个同事(沐剑)写的文章,国外有一家专门做 ...

  9. Oracle 数据库 Database Express Edition 11g Release 2 (11.2) 错误解决集锦(使用语法)

    ORA-14552: 在查询或 DML 中无法执行 DDL, 提交或回退 PL/SQL“ORA-14551:无法在查询中执行DML操作 解决:在声明函数时加上: PRAGMA AUTONOMOUS_T ...

  10. jEdit应用指南【基础篇】

    jEdit是Java编写,强大,易用的程序员文本编辑器 jEdit是一个成熟的,设计优秀的程序员文本编辑器,已经有了7年的开发历史.在功能和易用性方面压倒许多昂贵的开发工具时,jEdit在GNU公用许 ...