1 基本使用
文档地址:https://www.jqueryui.org.cn/tutorial/27.html
下载地址:https://jqueryui.com/download/,选择需要的组件,点击下载
1.1 示例
1.1.1 日期选择器
- 引入jquery-ui.css,jquery.js,jquery-ui.js
- 编写dom元素
- 编写js ```html <!doctype html>
日期:
显示效果:<br /><a name="tKYYX"></a>#### 1.1.2 进度条```javascript<!doctype html><html lang="en"><head><meta charset="utf-8"><title>jQuery UI 进度条(Progressbar) - 默认功能</title><link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css"><script src="//code.jquery.com/jquery-1.9.1.js"></script><script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script><link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css"><script>$(function() {$( "#progressbar" ).progressbar({value: 37});});</script></head><body><div id="progressbar"></div></body></html>
1.2 常用功能
1.2.1 初始化
$( "#progressbar" ).progressbar();
这将会初始化 jQuery 对象中的每个元素,在本例中,元素 id 为 “elem”。因为我们调用无参数的 .progressbar() 方法,小部件则会按照它的默认选项进行初始化。我们可以在安装时传递一组选项,这样既可重写默认选项。
$( "#progressbar" ).progressbar({ value: 20 });
安装时传递的选项数目多少可根据我们的需要而定。任何我们未传递的选项则都使用它们的默认值。
选项是小部件状态的组成部分,所以我们也可以在安装后再进行设置选项。我们将在后续的 option 方法中介绍这部分内容。
1.2.2 方法
既然小部件已经初始化,我们就可以查询它的状态,或者在小部件上执行动作。所有初始化后的动作都以方法调用的形式进行。为了在小部件上调用一个方法,我们可以向 jQuery 插件传递方法的名称。例如,为了在进度条(progressbar)小部件上调用 value 方法,我们应该使用:
// 查询value的值$( "#progressbar" ).progressbar( "value" );
如果方法接受参数,我们可以在方法名后传递参数。例如,为了传递参数 40 给 value 方法,我们可以使用:
// 修改进度为40$( "#progressbar" ).progressbar( "value", 40 );
就像 jQuery 中的其他方法一样,大部分的小部件方法为链接返回 jQuery 对象。
$( "#progressbar" ).progressbar( "value", 90 ).addClass( "almost-done" );
公共的方法
每个小部件都有它自己的一套基于小部件所提供功能的方法。然而,有一些方法是所有小部件都共同具有的。
- option
option,选项,通过option来改变插件的值,会有默认值。
// 通过option设置value$( "#elem" ).progressbar( "option", "value" );// 通过option,改变value$( "#elem" ).progressbar( "option", "value", 30 );// 通过传一个对象,改变多个选项$( "#elem" ).progressbar( "option", { value: 100, disabled: true});
和很多jQuery方法一样,传一个值就是查询,传两个值就是设置,只是这里需要传第一个参数option
- disable、enable
disable 方法禁用小部件。在进度条(progressbar)实例中,这会改变样式让进度条显示为禁用状态。
// 调用 disable 方法等同于设置 disabled 选项为 true。$( "#elem" ).progressbar( "disable" );// 调用 enable 方法等同于设置 disabled 选项为 false。$( "#elem" ).progressbar( "enable" );
- destroy、widget
- destroy
如果您不再需要小部件,那么可以销毁它,返回到最初的标记。这意味着小部件生命周期的终止。
$( "#elem" ).progressbar( "destroy" );
一旦您销毁了一个小部件,您就不能在该部件上调用任何方法,除非您再次初始化这个小部件。如果您要移除元素,可以直接通过 .remove(),也可以通过 .html() 或 .empty() 修改祖先,小部件会自动销毁。
- widget
一些小部件生成包装器元素,或与原始元素断开连接的元素。在下面的实例中,widget 将返回生成的元素。在进度条(progressbar)实例中,没有生成的包装器,widget 方法返回原始的元素。
// 返回包装id为progressbar的div的jquery对象console.log($( "#progressbar" ).progressbar( "widget" ));
1.2.3 事件
所有的小部件都有跟他们各种行为相关的事件,用于在状态改变时通知您。对于大多数的小部件,当事件被触发时,名称以小部件名称为前缀。例如,我们可以绑定进度条()的 change 事件,一旦值发生变化时就触发。
$( "#elem" ).bind( "progressbarchange", function() {alert( "The value has changed!" );});
每个事件都有一个相对应的回调,作为选项进行呈现。我们可以使用进度条(progressbar)的 change 回调,这等同于绑定 progressbarchange 事件。
$( "#elem" ).progressbar({change: function() {alert( "The value has changed!" );}});
公共的事件
大多数事件是针对特定的小部件,所有的小部件都有一个公共的 create 事件。该事件在小部件被创建时即被触发。
2 Widget Factory
文档地址:https://www.jqueryui.org.cn/tutorial/3689.html
2.1 jquery ui为什么使用部件库
- 无状态 vs. 有状态插件
大多数 jQuery 插件是无状态的,它们执行一些动作即完成了它们的任务。例如,如果您使用 .text( “hello” ) 设置元素的文本,没有安装阶段,结果都是一样的。对于这种类型的插件,它只是扩展了 jQuery 的原型。
然而,一些插件是有状态的,它们有全生命周期、维持状态以及对变化的反应。这些插件需要大量专门的代码来初始化和状态管理(有时是销毁)。这就导致出现了用于创建有状态插件的模板。更糟糕的是,每个插件的作者按照不同的方式进行管理插件的生命周期和状态,这就导致了不同的插件有不同的 API 样式。部件库(Widget Factory)旨在解决这些问题,它移除了模板,并为插件创建了一个一致的 API。
- 一致的 API
部件库(Widget Factory)定义了如何创建和销毁小部件,获取和设置选项,调用方法,以及监听小部件触发的事件。通过使用部件库(Widget Factory)来创建有状态的插件,会自动符合定义的标准,让新用户更容易使用您的插件。另外,部件库(Widget Factory)还能实现定义接口的功能。如果您对部件库(Widget Factory)提供的 API 还不熟悉,请查看 如何使用部件库(Widget Factory)。
- 在初始化时设置选项
当您创建一个接受选项的插件时,您应该为尽可能多的选项定义 defaults。然后在初始化时,把用户提供的选项与 defaults 进行合并。您也可以暴露 defaults,这样用户就可以更改默认值。在 jQuery 插件中,一个常用的模式如下所示:
$.fn.plugin = function( options ) {options = $.extend( {}, $.fn.plugin.defaults, options );// Plugin logic goes here.};$.fn.plugin.defaults = {param1: "foo",param2: "bar",param3: "baz"};
部件库(Widget Factory)也提供了这个功能,并在这上面做了改进。使用部件库(Widget Factory)之后,它将如下所示。
$.widget( "ns.plugin", {// Default options.options: {param1: "foo",param2: "bar",param3: "baz"},_create: function() {// Options are already merged and stored in this.options// Plugin logic goes here.}});
2.2 创建插件
// custom是命名空间// progressbar是插件的名字,通过jquery.fn将progressbar方法加到了jquery的原型上$.widget( "custom.progressbar", {// 插件的默认值options: {value: 0},// 私有方法用_开头_create: function() {var progress = this.options.value + "%";this.element.addClass( "progressbar" ).text( progress );},// 公有方法没有下划线value: function( value ) {// No value passed, act as a getter.if ( value === undefined ) {return this.options.value;}// Value passed, act as a setter.this.options.value = this._constrain( value );var progress = this.options.value + "%";this.element.text( progress );},// 私有方法用_开头_constrain: function( value ) {if ( value > 100 ) {value = 100;}if ( value < 0 ) {value = 0;}return value;}});
2.3 调用插件
使用小部件的插件调用方法,把方法名称以字符串形式进行传递。
// $( ".selector" )是创建dialog的jquery对象$( ".selector" ).dialog( "close" );// 需要传参数的option方法,会返回option中height的值$( ".selector" ).dialog( "option", "height" );
2.3.1 实例调用
每个小部件的每个实例都是使用 jQuery.data() 存储在元素上。为了检索实例对象,请使用小部件的全称作为键名调用 jQuery.data()。具体如下面实例所示。
var dialog = $( ".selector" ).data( "ui-dialog" );dialog.close();
在 jQuery UI 1.11 中,新的 instance() 方法会使得这个过程变得更简单。
$( ".selector" ).dialog( "instance" ).close();
2.3.2 返回类型
大多数通过小部件的插件调用的方法将返回一个 jQuery 对象,所以方法调用可以通过额外的 jQuery 方法链接。当在实例上进行调用时,则会返回 undefined。具体如下面实例所示。
var dialog = $( ".selector" ).dialog();// Instance invocation - returns undefineddialog.data( "ui-dialog" ).close();// Plugin invocation - returns a jQuery objectdialog.dialog( "close" );// Therefore, plugin method invocation makes it possible to// chain method calls with other jQuery functionsdialog.dialog( "close" ).css( "color", "red" );
例外的是,返回小部件相关信息的那些方法。例如 dialog(对话框)的isOpen()方法。
$( ".selector" ).dialog( "isOpen" )// This will throw a TypeError.css( "color", "red" );
这会产生一个 TypeError 错误,因为 isOpen() 返回的是一个布尔值,而不是一个 jQuery 对象。
2.3 添加回调
最简单的扩展插件的方法是添加回调,这样用户就可以在插件状态发生变化时做出反应。我们可以看下面的实例如何在进度达到 100% 时添加回调到进度条。
- _trigger() 方法有三个参数:回调名称,一个启动回调的 jQuery 事件对象,以及一个与事件相关的数据哈希。
- 回调名称是唯一一个必需的参数,但是对于想要在插件上实现自定义功能的用户,其他的参数是非常有用的。
- 例如,如果我们创建一个可拖拽插件,我们可以在触发拖拽回调时传递 mousemove 事件,这将允许用户对基于由事件对象提供的 x/y 坐标上的拖拽做出反应。
- 请注意,传递到 _trigger() 的原始的事件必须是一个 jQuery 事件,而不是一个原生的浏览器事件。
回调函数本质上只是附加选项,所以您可以像其他选项一样获取并设置它们。无论何时执行回调,都会有一个相对应的事件被触发。事件类型是通过连接插件的名称和回调函数名称确定的。回调和事件都接受两个相同的参数:一个事件对象和一个与事件相关的数据哈希,具体如下面实例所示。您的插件可能需要包含防止用户使用的功能,为了做到这点,最好的方法就是创建你可撤销的回调。用户可以撤销回调或者相关的事件,与他们撤销任何一个原生事件一样,都是通过调用 event.preventDefault() 或返回 false 来实现的。如果用户撤销回调,_trigger() 方法将返回 false,这样您就能在插件内实现合适的功能。 ```javascript // 在创建插件的时候,传递回调函数 var bar = $( ““ ) .appendTo( “body” ) .progressbar({$.widget( "custom.progressbar", {options: {value: 0},_create: function() {this.options.value = this._constrain(this.options.value);this.element.addClass( "progressbar" );this.refresh();},_setOption: function( key, value ) {if ( key === "value" ) {value = this._constrain( value );}this._super( key, value );},_setOptions: function( options ) {this._super( options );this.refresh();},refresh: function() {var progress = this.options.value + "%";this.element.text( progress );if ( this.options.value == 100 ) {// 添加名为complete的回调函数this._trigger( "complete", null, { value: 100 } );}},_constrain: function( value ) {if ( value > 100 ) {value = 100;}if ( value < 0 ) {value = 0;}return value;}});
}) .bind( “progressbarcomplete”, function( event, data ) {complete: function( event, data ) {alert( "Callbacks are great!" );}
});alert( "Events bubble and support many handlers for extreme flexibility." );alert( "The progress bar value is " + data.value );
bar.progressbar( “option”, “value”, 100 );
<a name="ci3cK"></a>### 2.4 本质现在我们已经看到如何使用部件库(Widget Factory)创建一个插件,接下来让我们看看它实际上是如何工作的。- 当您调用 jQuery.widget() 时,它将为插件创建一个构造函数,并设置您为插件实例传入的作为原型的对象。所有自动添加到插件的功能都来自一个基本的小部件原型,该原型定义为 jQuery.Widget.prototype。- 当创建插件实例时,会使用 jQuery.data 把它存储在原始的 DOM 元素上,插件名作为键名。由于插件实例直接链接到 DOM 元素上,您可以直接访问插件实例,而不需要遍历插件方法。这将允许您直接在插件实例上调用方法,而不需要传递字符串形式的方法名,同时您也可以直接访问插件的属性。```javascriptvar 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 );
您也可以在不遍历插件方法的情况下创建一个实例,通过选项和元素直接调用构造函数即可:
var bar = $.custom.progressbar( {}, $( "<div></div>" ).appendTo( "body") );// Same result as before.alert( bar.options.value );
2.5 扩展插件的原型
插件有构造函数和原型的最大好处是易于扩展插件。通过添加或修改插件原型上的方法,我们可以修改插件所有实例的行为。例如,如果我们想要向进度条添加一个方法来重置进度为 0%,我们可以向原型添加这个方法,它将在所有插件实例上可调用。
$.custom.progressbar.prototype.reset = function() {this._setOption( "value", 0 );};
2.6 清理
在某些情况下,允许用户应用插件,然后再取消应用。您可以通过 _destroy() 方法做到这一点。在 _destroy() 方法内,您应该撤销在初始化和后期使用期间插件所做的一切动作。_destroy() 是通过 .destroy() 方法被调用的,.destroy() 方法是在插件实例绑定的元素从 DOM 上移除时被自动调用的,所以这可被用于垃圾回收。基本的 .destroy() 方法也处理一些常用的清理操作,比如从小部件的 DOM 元素上移除实例引用,从元素上解除绑定小部件命名空间中的所有事件,解除绑定所有使用 _bind() 添加的事件。
$.widget( "custom.progressbar", {options: {value: 0},_create: function() {this.options.value = this._constrain(this.options.value);this.element.addClass( "progressbar" );this.refresh();},_setOption: function( key, value ) {if ( key === "value" ) {value = this._constrain( value );}this._super( key, value );},_setOptions: function( options ) {this._super( options );this.refresh();},refresh: function() {var progress = this.options.value + "%";this.element.text( progress );if ( this.options.value == 100 ) {this._trigger( "complete", null, { value: 100 } );}},_constrain: function( value ) {if ( value > 100 ) {value = 100;}if ( value < 0 ) {value = 0;}return value;},_destroy: function() {this.element.removeClass( "progressbar" ).text( "" );}});
2.8 总结
部件库(Widget Factory)只是创建有状态插件的一种方式。这里还有一些其他不同的模型可以使用,且每个都有各自的优势和劣势。部件库(Widget Factory)解决了很多常见的问题,且大大提高了效率,同时也大大提高了代码的重用性,使它适合于 jQuery UI 及其他有状态的插件。
请注意,在本章节中我们使用了 custom 命名空间。ui 命名空间被官方的 jQuery UI 插件保留。当创建您自己的插件时,您应该创建自己的命名空间。这样才能更清楚插件来自哪里,属于哪个范围。
3 扩展小部件
3.1 创建新的小部件
通过部件库(Widget Factory)创建小部件是通过向 $.widget() 传递小部件名称和一个原型对象来完成的。下面的实例是在 “custom” 命名空间中创建一个 “superDialog” 小部件。
参数:插件名称,原型对象
$.widget( "custom.superDialog", {} );
为了支持扩展,$.widget() 可选性地接受作为父部件使用的小部件的构造函数。当指定一个父部件时,把它作为第二个参数进行传递,放在小部件名称后面,在小部件原型对象前面。
参数:插件名称,父插件,原型对象
$.widget( "custom.superDialog", $.ui.dialog, {} );
添加非空的原型对象:
$.widget( "custom.superDialog", $.ui.dialog, {red: function() {this.element.css( "color", "red" );}});// Create a new <div>, convert it into a superDialog, and call the red() method.$( "<div>I am red</div>" ).superDialog().superDialog( "red" );
3.2 扩展已有的方法
// 重写open方法,不会打开对话框,而是输出open$.widget( "custom.superDialog", $.ui.dialog, {open: function() {console.log( "open" );}});// Create a new <div>, and convert it into a superDialog.$( "<div>" ).superDialog();
// 打开对话框,并且做一些事情$.widget( "custom.superDialog", $.ui.dialog, {open: function() {console.log( "open" );// Invoke the parent widget's open().return this._super();}});$( "<div>" ).superDialog();
_super() 和 _superApply() 实际上等同于最初的 Function.prototype.call() 和 Function.prototype.apply() 方法。因此,_super() 接受一个参数列表,_superApply() 接受一个数组作为参数。下面的实例演示了这二者之间的不同。
$.widget( "custom.superDialog", $.ui.dialog, {_setOption: function( key, value ) {// Both invoke dialog's setOption() method. _super() requires the arguments// be passed as an argument list, _superApply() as a single array.this._super( key, value );this._superApply( arguments );}});
3.3 重定义小部件
jQuery UI 1.9 添加了重定义小部件的功能。因此,可以不用创建一个新的小部件,我们只需要传递 $.widget() 这样一个已有的小部件名称和构造函数即可。下面的实例在 open() 中添加了相同的记录,但不是通过创建一个新的小部件来完成的。
$.widget( "ui.dialog", $.ui.dialog, {open: function() {console.log( "open" );return this._super();}});$( "<div>" ).dialog();
通过这个方法,我们可以扩展一个已有的小部件方法,但是仍然可以使用 _super() 来访问原始的方法 - 这些都不是通过创建一个新的小部件来完成的,而是直接重定义小部件即可。
3.4 小部件(Widgets)和多态性(Polymorphism)
当在小部件扩展及它们的插件之间进行交互时候,有一点值得注意,父部件的插件不能用来调用子部件元素上的方法。下面的实例演示了这一点。
$.widget( "custom.superDialog", $.ui.dialog, {} );var dialog = $( "<div>" ).superDialog();// This works.dialog.superDialog( "close" );// This doesn't.dialog.dialog( "close" );
3.5 定制个性化实例
目前为止,我们看到的实例都有在小部件原型上扩展的方法。在原型上重载的方法影响了小部件的所有实例。
为了演示这一点,请看下面的实例。dialog(对话框)的两个势力都使用了相同的 open() 方法。
$.widget( "ui.dialog", $.ui.dialog, {open: function() {console.log( "open" );return this._super();}});// Create two dialogs, both use the same open(), therefore "open" is logged twice.$( "<div>" ).dialog();$( "<div>" ).dialog();
有时候,您只需要改变小部件的某个实例的行为。为了做到这点,您需要使用正常的 JavaScript 属性分配,获得对实例的引用,并重载该方法。具体如下面实例所示。
var dialogInstance = $( "<div>" ).dialog()// Retrieve the dialog's instance and store it..data( "ui-dialog" );// Override the close() method for this dialogdialogInstance.close = function() {console.log( "close" );};// Create a second dialog$( "<div>" ).dialog();// Select both dialogs and call close() on each of them.// "close" will only be logged once.$( ":data(ui-dialog)" ).dialog( "close" );
个性化实例的重载方法技术是完美的一次性定制。
