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>

日期:

  1. 显示效果:<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22310040/1628413863627-65da887d-a887-4bf0-99e8-650e1dd932b9.png#clientId=ubd5854bb-23df-4&from=paste&height=276&id=u7177c610&margin=%5Bobject%20Object%5D&name=image.png&originHeight=276&originWidth=476&originalType=binary&ratio=1&size=12858&status=done&style=none&taskId=u8c519860-bbaf-4a07-9c7d-3de629ed06c&width=476)
  2. <a name="tKYYX"></a>
  3. #### 1.1.2 进度条
  4. ```javascript
  5. <!doctype html>
  6. <html lang="en">
  7. <head>
  8. <meta charset="utf-8">
  9. <title>jQuery UI 进度条(Progressbar) - 默认功能</title>
  10. <link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
  11. <script src="//code.jquery.com/jquery-1.9.1.js"></script>
  12. <script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
  13. <link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css">
  14. <script>
  15. $(function() {
  16. $( "#progressbar" ).progressbar({
  17. value: 37
  18. });
  19. });
  20. </script>
  21. </head>
  22. <body>
  23. <div id="progressbar"></div>
  24. </body>
  25. </html>

显示效果:
image.png

1.2 常用功能

1.2.1 初始化

  1. $( "#progressbar" ).progressbar();

这将会初始化 jQuery 对象中的每个元素,在本例中,元素 id 为 “elem”。因为我们调用无参数的 .progressbar() 方法,小部件则会按照它的默认选项进行初始化。我们可以在安装时传递一组选项,这样既可重写默认选项。

  1. $( "#progressbar" ).progressbar({ value: 20 });

安装时传递的选项数目多少可根据我们的需要而定。任何我们未传递的选项则都使用它们的默认值。
选项是小部件状态的组成部分,所以我们也可以在安装后再进行设置选项。我们将在后续的 option 方法中介绍这部分内容。

1.2.2 方法

既然小部件已经初始化,我们就可以查询它的状态,或者在小部件上执行动作。所有初始化后的动作都以方法调用的形式进行。为了在小部件上调用一个方法,我们可以向 jQuery 插件传递方法的名称。例如,为了在进度条(progressbar)小部件上调用 value 方法,我们应该使用:

  1. // 查询value的值
  2. $( "#progressbar" ).progressbar( "value" );

如果方法接受参数,我们可以在方法名后传递参数。例如,为了传递参数 40 给 value 方法,我们可以使用:

  1. // 修改进度为40
  2. $( "#progressbar" ).progressbar( "value", 40 );

就像 jQuery 中的其他方法一样,大部分的小部件方法为链接返回 jQuery 对象。

  1. $( "#progressbar" )
  2. .progressbar( "value", 90 )
  3. .addClass( "almost-done" );

公共的方法
每个小部件都有它自己的一套基于小部件所提供功能的方法。然而,有一些方法是所有小部件都共同具有的。

  • option

option,选项,通过option来改变插件的值,会有默认值。

  1. // 通过option设置value
  2. $( "#elem" ).progressbar( "option", "value" );
  3. // 通过option,改变value
  4. $( "#elem" ).progressbar( "option", "value", 30 );
  5. // 通过传一个对象,改变多个选项
  6. $( "#elem" ).progressbar( "option", { value: 100, disabled: true});

和很多jQuery方法一样,传一个值就是查询,传两个值就是设置,只是这里需要传第一个参数option

  • disable、enable

disable 方法禁用小部件。在进度条(progressbar)实例中,这会改变样式让进度条显示为禁用状态。

  1. // 调用 disable 方法等同于设置 disabled 选项为 true。
  2. $( "#elem" ).progressbar( "disable" );
  3. // 调用 enable 方法等同于设置 disabled 选项为 false。
  4. $( "#elem" ).progressbar( "enable" );
  • destroy、widget
    • destroy

如果您不再需要小部件,那么可以销毁它,返回到最初的标记。这意味着小部件生命周期的终止。

  1. $( "#elem" ).progressbar( "destroy" );

一旦您销毁了一个小部件,您就不能在该部件上调用任何方法,除非您再次初始化这个小部件。如果您要移除元素,可以直接通过 .remove(),也可以通过 .html() 或 .empty() 修改祖先,小部件会自动销毁。

  • widget

一些小部件生成包装器元素,或与原始元素断开连接的元素。在下面的实例中,widget 将返回生成的元素。在进度条(progressbar)实例中,没有生成的包装器,widget 方法返回原始的元素。

  1. // 返回包装id为progressbar的div的jquery对象
  2. console.log($( "#progressbar" ).progressbar( "widget" ));

1.2.3 事件

所有的小部件都有跟他们各种行为相关的事件,用于在状态改变时通知您。对于大多数的小部件,当事件被触发时,名称以小部件名称为前缀。例如,我们可以绑定进度条()的 change 事件,一旦值发生变化时就触发。

  1. $( "#elem" ).bind( "progressbarchange", function() {
  2. alert( "The value has changed!" );
  3. });

每个事件都有一个相对应的回调,作为选项进行呈现。我们可以使用进度条(progressbar)的 change 回调,这等同于绑定 progressbarchange 事件。

  1. $( "#elem" ).progressbar({
  2. change: function() {
  3. alert( "The value has changed!" );
  4. }});

公共的事件
大多数事件是针对特定的小部件,所有的小部件都有一个公共的 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 插件中,一个常用的模式如下所示:

  1. $.fn.plugin = function( options ) {
  2. options = $.extend( {}, $.fn.plugin.defaults, options );
  3. // Plugin logic goes here.
  4. };
  5. $.fn.plugin.defaults = {
  6. param1: "foo",
  7. param2: "bar",
  8. param3: "baz"
  9. };

部件库(Widget Factory)也提供了这个功能,并在这上面做了改进。使用部件库(Widget Factory)之后,它将如下所示。

  1. $.widget( "ns.plugin", {
  2. // Default options.
  3. options: {
  4. param1: "foo",
  5. param2: "bar",
  6. param3: "baz"
  7. },
  8. _create: function() {
  9. // Options are already merged and stored in this.options
  10. // Plugin logic goes here.
  11. }
  12. });

2.2 创建插件

  1. // custom是命名空间
  2. // progressbar是插件的名字,通过jquery.fn将progressbar方法加到了jquery的原型上
  3. $.widget( "custom.progressbar", {
  4. // 插件的默认值
  5. options: {
  6. value: 0
  7. },
  8. // 私有方法用_开头
  9. _create: function() {
  10. var progress = this.options.value + "%";
  11. this.element
  12. .addClass( "progressbar" )
  13. .text( progress );
  14. },
  15. // 公有方法没有下划线
  16. value: function( value ) {
  17. // No value passed, act as a getter.
  18. if ( value === undefined ) {
  19. return this.options.value;
  20. }
  21. // Value passed, act as a setter.
  22. this.options.value = this._constrain( value );
  23. var progress = this.options.value + "%";
  24. this.element.text( progress );
  25. },
  26. // 私有方法用_开头
  27. _constrain: function( value ) {
  28. if ( value > 100 ) {
  29. value = 100;
  30. }
  31. if ( value < 0 ) {
  32. value = 0;
  33. }
  34. return value;
  35. }
  36. });

2.3 调用插件

使用小部件的插件调用方法,把方法名称以字符串形式进行传递。

  1. // $( ".selector" )是创建dialog的jquery对象
  2. $( ".selector" ).dialog( "close" );
  3. // 需要传参数的option方法,会返回option中height的值
  4. $( ".selector" ).dialog( "option", "height" );

2.3.1 实例调用

每个小部件的每个实例都是使用 jQuery.data() 存储在元素上。为了检索实例对象,请使用小部件的全称作为键名调用 jQuery.data()。具体如下面实例所示。

  1. var dialog = $( ".selector" ).data( "ui-dialog" );
  2. dialog.close();

在 jQuery UI 1.11 中,新的 instance() 方法会使得这个过程变得更简单。

  1. $( ".selector" ).dialog( "instance" ).close();

2.3.2 返回类型

大多数通过小部件的插件调用的方法将返回一个 jQuery 对象,所以方法调用可以通过额外的 jQuery 方法链接。当在实例上进行调用时,则会返回 undefined。具体如下面实例所示。

  1. var dialog = $( ".selector" ).dialog();
  2. // Instance invocation - returns undefined
  3. dialog.data( "ui-dialog" ).close();
  4. // Plugin invocation - returns a jQuery object
  5. dialog.dialog( "close" );
  6. // Therefore, plugin method invocation makes it possible to
  7. // chain method calls with other jQuery functions
  8. dialog.dialog( "close" )
  9. .css( "color", "red" );

例外的是,返回小部件相关信息的那些方法。例如 dialog(对话框)的isOpen()方法

  1. $( ".selector" )
  2. .dialog( "isOpen" )
  3. // This will throw a TypeError
  4. .css( "color", "red" );

这会产生一个 TypeError 错误,因为 isOpen() 返回的是一个布尔值,而不是一个 jQuery 对象。

2.3 添加回调

最简单的扩展插件的方法是添加回调,这样用户就可以在插件状态发生变化时做出反应。我们可以看下面的实例如何在进度达到 100% 时添加回调到进度条。

  • _trigger() 方法有三个参数:回调名称,一个启动回调的 jQuery 事件对象,以及一个与事件相关的数据哈希。
  • 回调名称是唯一一个必需的参数,但是对于想要在插件上实现自定义功能的用户,其他的参数是非常有用的。
  • 例如,如果我们创建一个可拖拽插件,我们可以在触发拖拽回调时传递 mousemove 事件,这将允许用户对基于由事件对象提供的 x/y 坐标上的拖拽做出反应。
  • 请注意,传递到 _trigger() 的原始的事件必须是一个 jQuery 事件,而不是一个原生的浏览器事件。
    1. $.widget( "custom.progressbar", {
    2. options: {
    3. value: 0
    4. },
    5. _create: function() {
    6. this.options.value = this._constrain(this.options.value);
    7. this.element.addClass( "progressbar" );
    8. this.refresh();
    9. },
    10. _setOption: function( key, value ) {
    11. if ( key === "value" ) {
    12. value = this._constrain( value );
    13. }
    14. this._super( key, value );
    15. },
    16. _setOptions: function( options ) {
    17. this._super( options );
    18. this.refresh();
    19. },
    20. refresh: function() {
    21. var progress = this.options.value + "%";
    22. this.element.text( progress );
    23. if ( this.options.value == 100 ) {
    24. // 添加名为complete的回调函数
    25. this._trigger( "complete", null, { value: 100 } );
    26. }
    27. },
    28. _constrain: function( value ) {
    29. if ( value > 100 ) {
    30. value = 100;
    31. }
    32. if ( value < 0 ) {
    33. value = 0;
    34. }
    35. return value;
    36. }
    37. });
    回调函数本质上只是附加选项,所以您可以像其他选项一样获取并设置它们。无论何时执行回调,都会有一个相对应的事件被触发。事件类型是通过连接插件的名称和回调函数名称确定的。回调和事件都接受两个相同的参数:一个事件对象和一个与事件相关的数据哈希,具体如下面实例所示。您的插件可能需要包含防止用户使用的功能,为了做到这点,最好的方法就是创建你可撤销的回调。用户可以撤销回调或者相关的事件,与他们撤销任何一个原生事件一样,都是通过调用 event.preventDefault() 或返回 false 来实现的。如果用户撤销回调,_trigger() 方法将返回 false,这样您就能在插件内实现合适的功能。 ```javascript // 在创建插件的时候,传递回调函数 var bar = $( “
    “ ) .appendTo( “body” ) .progressbar({
    1. complete: function( event, data ) {
    2. alert( "Callbacks are great!" );
    3. }
    }) .bind( “progressbarcomplete”, function( event, data ) {
    1. alert( "Events bubble and support many handlers for extreme flexibility." );
    2. alert( "The progress bar value is " + data.value );
    });

bar.progressbar( “option”, “value”, 100 );

  1. <a name="ci3cK"></a>
  2. ### 2.4 本质
  3. 现在我们已经看到如何使用部件库(Widget Factory)创建一个插件,接下来让我们看看它实际上是如何工作的。
  4. - 当您调用 jQuery.widget() 时,它将为插件创建一个构造函数,并设置您为插件实例传入的作为原型的对象。所有自动添加到插件的功能都来自一个基本的小部件原型,该原型定义为 jQuery.Widget.prototype。
  5. - 当创建插件实例时,会使用 jQuery.data 把它存储在原始的 DOM 元素上,插件名作为键名。
  6. 由于插件实例直接链接到 DOM 元素上,您可以直接访问插件实例,而不需要遍历插件方法。这将允许您直接在插件实例上调用方法,而不需要传递字符串形式的方法名,同时您也可以直接访问插件的属性。
  7. ```javascript
  8. var bar = $( "<div></div>" )
  9. .appendTo( "body" )
  10. .progressbar()
  11. .data( "progressbar" );
  12. // Call a method directly on the plugin instance.
  13. bar.option( "value", 50 );
  14. // Access properties on the plugin instance.
  15. alert( bar.options.value );

您也可以在不遍历插件方法的情况下创建一个实例,通过选项和元素直接调用构造函数即可:

  1. var bar = $.custom.progressbar( {}, $( "<div></div>" ).appendTo( "body") );
  2. // Same result as before.
  3. alert( bar.options.value );

2.5 扩展插件的原型

插件有构造函数和原型的最大好处是易于扩展插件。通过添加或修改插件原型上的方法,我们可以修改插件所有实例的行为。例如,如果我们想要向进度条添加一个方法来重置进度为 0%,我们可以向原型添加这个方法,它将在所有插件实例上可调用。

  1. $.custom.progressbar.prototype.reset = function() {
  2. this._setOption( "value", 0 );
  3. };

2.6 清理

在某些情况下,允许用户应用插件,然后再取消应用。您可以通过 _destroy() 方法做到这一点。在 _destroy() 方法内,您应该撤销在初始化和后期使用期间插件所做的一切动作。_destroy() 是通过 .destroy() 方法被调用的,.destroy() 方法是在插件实例绑定的元素从 DOM 上移除时被自动调用的,所以这可被用于垃圾回收。基本的 .destroy() 方法也处理一些常用的清理操作,比如从小部件的 DOM 元素上移除实例引用,从元素上解除绑定小部件命名空间中的所有事件,解除绑定所有使用 _bind() 添加的事件。

  1. $.widget( "custom.progressbar", {
  2. options: {
  3. value: 0
  4. },
  5. _create: function() {
  6. this.options.value = this._constrain(this.options.value);
  7. this.element.addClass( "progressbar" );
  8. this.refresh();
  9. },
  10. _setOption: function( key, value ) {
  11. if ( key === "value" ) {
  12. value = this._constrain( value );
  13. }
  14. this._super( key, value );
  15. },
  16. _setOptions: function( options ) {
  17. this._super( options );
  18. this.refresh();
  19. },
  20. refresh: function() {
  21. var progress = this.options.value + "%";
  22. this.element.text( progress );
  23. if ( this.options.value == 100 ) {
  24. this._trigger( "complete", null, { value: 100 } );
  25. }
  26. },
  27. _constrain: function( value ) {
  28. if ( value > 100 ) {
  29. value = 100;
  30. }
  31. if ( value < 0 ) {
  32. value = 0;
  33. }
  34. return value;
  35. },
  36. _destroy: function() {
  37. this.element
  38. .removeClass( "progressbar" )
  39. .text( "" );
  40. }
  41. });

2.8 总结

部件库(Widget Factory)只是创建有状态插件的一种方式。这里还有一些其他不同的模型可以使用,且每个都有各自的优势和劣势。部件库(Widget Factory)解决了很多常见的问题,且大大提高了效率,同时也大大提高了代码的重用性,使它适合于 jQuery UI 及其他有状态的插件。
请注意,在本章节中我们使用了 custom 命名空间。ui 命名空间被官方的 jQuery UI 插件保留。当创建您自己的插件时,您应该创建自己的命名空间。这样才能更清楚插件来自哪里,属于哪个范围。

3 扩展小部件

3.1 创建新的小部件

通过部件库(Widget Factory)创建小部件是通过向 $.widget() 传递小部件名称和一个原型对象来完成的。下面的实例是在 “custom” 命名空间中创建一个 “superDialog” 小部件。
参数:插件名称,原型对象

  1. $.widget( "custom.superDialog", {} );

为了支持扩展,$.widget() 可选性地接受作为父部件使用的小部件的构造函数。当指定一个父部件时,把它作为第二个参数进行传递,放在小部件名称后面,在小部件原型对象前面。
参数:插件名称,父插件,原型对象

  1. $.widget( "custom.superDialog", $.ui.dialog, {} );

添加非空的原型对象:

  1. $.widget( "custom.superDialog", $.ui.dialog, {
  2. red: function() {
  3. this.element.css( "color", "red" );
  4. }
  5. });
  6. // Create a new <div>, convert it into a superDialog, and call the red() method.
  7. $( "<div>I am red</div>" )
  8. .superDialog()
  9. .superDialog( "red" );

3.2 扩展已有的方法

  1. // 重写open方法,不会打开对话框,而是输出open
  2. $.widget( "custom.superDialog", $.ui.dialog, {
  3. open: function() {
  4. console.log( "open" );
  5. }
  6. });
  7. // Create a new <div>, and convert it into a superDialog.
  8. $( "<div>" ).superDialog();
  1. // 打开对话框,并且做一些事情
  2. $.widget( "custom.superDialog", $.ui.dialog, {
  3. open: function() {
  4. console.log( "open" );
  5. // Invoke the parent widget's open().
  6. return this._super();
  7. }
  8. });
  9. $( "<div>" ).superDialog();

_super() 和 _superApply() 实际上等同于最初的 Function.prototype.call() 和 Function.prototype.apply() 方法。因此,_super() 接受一个参数列表,_superApply() 接受一个数组作为参数。下面的实例演示了这二者之间的不同。

  1. $.widget( "custom.superDialog", $.ui.dialog, {
  2. _setOption: function( key, value ) {
  3. // Both invoke dialog's setOption() method. _super() requires the arguments
  4. // be passed as an argument list, _superApply() as a single array.
  5. this._super( key, value );
  6. this._superApply( arguments );
  7. }
  8. });

3.3 重定义小部件

jQuery UI 1.9 添加了重定义小部件的功能。因此,可以不用创建一个新的小部件,我们只需要传递 $.widget() 这样一个已有的小部件名称和构造函数即可。下面的实例在 open() 中添加了相同的记录,但不是通过创建一个新的小部件来完成的。

  1. $.widget( "ui.dialog", $.ui.dialog, {
  2. open: function() {
  3. console.log( "open" );
  4. return this._super();
  5. }
  6. });
  7. $( "<div>" ).dialog();

通过这个方法,我们可以扩展一个已有的小部件方法,但是仍然可以使用 _super() 来访问原始的方法 - 这些都不是通过创建一个新的小部件来完成的,而是直接重定义小部件即可。

3.4 小部件(Widgets)和多态性(Polymorphism)

当在小部件扩展及它们的插件之间进行交互时候,有一点值得注意,父部件的插件不能用来调用子部件元素上的方法。下面的实例演示了这一点。

  1. $.widget( "custom.superDialog", $.ui.dialog, {} );
  2. var dialog = $( "<div>" ).superDialog();
  3. // This works.
  4. dialog.superDialog( "close" );
  5. // This doesn't.
  6. dialog.dialog( "close" );

3.5 定制个性化实例

目前为止,我们看到的实例都有在小部件原型上扩展的方法。在原型上重载的方法影响了小部件的所有实例。
为了演示这一点,请看下面的实例。dialog(对话框)的两个势力都使用了相同的 open() 方法。

  1. $.widget( "ui.dialog", $.ui.dialog, {
  2. open: function() {
  3. console.log( "open" );
  4. return this._super();
  5. }
  6. });
  7. // Create two dialogs, both use the same open(), therefore "open" is logged twice.
  8. $( "<div>" ).dialog();
  9. $( "<div>" ).dialog();

有时候,您只需要改变小部件的某个实例的行为。为了做到这点,您需要使用正常的 JavaScript 属性分配,获得对实例的引用,并重载该方法。具体如下面实例所示。

  1. var dialogInstance = $( "<div>" )
  2. .dialog()
  3. // Retrieve the dialog's instance and store it.
  4. .data( "ui-dialog" );
  5. // Override the close() method for this dialog
  6. dialogInstance.close = function() {
  7. console.log( "close" );
  8. };
  9. // Create a second dialog
  10. $( "<div>" ).dialog();
  11. // Select both dialogs and call close() on each of them.
  12. // "close" will only be logged once.
  13. $( ":data(ui-dialog)" ).dialog( "close" );

个性化实例的重载方法技术是完美的一次性定制。