当前位置: 首页 > 编程日记 > 正文

编写jQueryUI插件(widget)

使用jQueryUI的widget来写插件,相比于基本的jquery插件有一些好处:

* 方便实现继承,代码重用

* 默认是单例

* widget已经给你实现好的一些常用方法,例如destroy

带来好处的同时也带来了荆棘和陷阱,本文的目的就是梳理这些荆棘,标出哪里有陷阱。

基本知识:命名规范,public, private, this, this.element

如何开始写一个widget呢?模板如下:

(function ($) {// utility functions (won’t be inherited)function foo() {}$.widget('命名空间.插件名', $.继承插件的命名空间.插件名,{ /* snip */ });
})(jQuery);        

其中命名空间是可选的,要不要继承别的widget也是可选的。大头是后面snip的部分,这也是下文要讲的。

一般来说工具函数写在widget外面比较合适,但如果你想要这些工具函数被子类继承,则需要写在widget里面。

写在widget里面的,就有public和private之分,规则是:

public方法首字符不是_

private方法首字符是_


当调用方法时,会先判断是否以_开头,如果是则不执行调用。

如果我非要在外面调用private方法,该怎么做?并非一点办法也没有:

var instance = $('<div>');
instance.mywidget('publicFunction'); // work
instance.mywidget('_privateFunction'); // silently fail
instance.data('mywidget')._privateFunction(); // work
$.mynamespace.mywidget.prototype._privateFunction(); // work
 

在widget内,this表示的是什么?我们在widget的一个public函数内用console.log(this)打出来瞧瞧:

image

日志显示,this是一个$.widget.$.(anonymous function).(anonymous function)

this.element是变成widget的那个jQuery对象,如果要用jquery的方法,往往首先要取到jquery对象。

this.options是插件的选项,下文会详解。

this.__proto__包含了插件中定义的所有public和private函数,以及继承过来的方法。

这里简单介绍一下__proto__:每个对象都会在其内部初始化一个属性,就是__proto__,当我们访问一个对象的属性 时,如果这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就这样 一直找下去,也就是我们平时所说的原型链的概念。

_create  _init    destroy

widget factory实现了一种单例模式,即不允许在同一个jQuery对象上多次实例化。

当调用$(XX).widgetName()进行初始化的时候,会执行以下代码(源码截取自jquery.ui.widget.js):

var instance = $.data( this, name ); // 从widget自身取出名字为name的数据
if ( instance ) {instance.option( options || {} )._init();  // 若该数据已经存在则只调用_init
} else {$.data( this, name, new object( options, this ) ); // 若数据还没有则新建一个实例,并将实例保存
}

当调用$(XX).widgetName(‘destroy’)进行销毁的时候,执行以下代码(源码截取自jquery.ui.widget.js):

this.element.unbind( "." + this.widgetName ).removeData( this.widgetName ); // 删除在create时保存的数据 

有一个removeData的操作,那么下次调用$(XX).widgetName()就会重新实例化了。

需要注意的是,destroy方法在jquery.ui.widget.js中是有默认实现的,而_create和_init没有实现。因此如果用自己的方法覆盖destroy,不要忘记调用默认的

destory: function () {console.log('destory');// call the original destroy method since we overwrote it$.Widget.prototype.destroy.call(this);
}

以下示例代码验证_create和_init的区别以及destroy的作用:

var mw = $('#test').myWidget(); // _create  _init
mw = $('#test').myWidget(); // _init
mw.myWidget('destory');
mw = $('#test').myWidget(); // _create  _init

那么在_create和_init以及destroy里分别应该做什么:

_create: 生成HTML,事件绑定。

_init: 执行默认的初始化动作,例如把页面变成初始状态。

destory: 调用$.Widget.prototype.destroy.call(this),删除HTML。

注意:绑定事件要注意给事件名加命名空间后缀:例如 .bind('mouseenter.mywidget', this._hover)

options

选项,在widget中的定义是options,而在调用时是option,注意定义的时候有s,调用的时候没s。

定义:

option

s

: {field1: 'default',function1: function () {console.log('default option function1');}
},

调用:

$('#test').mywidget('option', 'field1', 2);

widget默认实现了两个函数:_setOptions和_setOption,_setOptions的实现就是对每个要修改的option调用_setOption,也就是说真正修改的动作在_setOption里。因此,如果要重写_setOption函数,则一定不要忘记写

$.Widget.prototype._setOption.apply(this, arguments);

_setOptions和_setOption这俩函数什么时候被调用呢?用下面这个例子来说明。

例如有这样的_setOption和_setOptions:

 
_setOption: function (key, value) {console.log('_setOption: key=%s  value=%s', key, value);$.Widget.prototype._setOption.apply(this, arguments);
},_setOptions: function (options) {var key;console.group('_setOptions');for (key in options) {this._setOption(key, options[key]);}console.groupEnd();return this;
},

以及一个打印options值的函数printOptions:

printOptions: function () {console.group('options');console.log('field1: %s', this.options.field1);console.log('function1: %s', this.options.function1);console.groupEnd();
},

我们像下面这样调用:

var instance = $('<div>');// create widget with default options
console.group();instance.mywidget(); 
instance.mywidget('printOptions');console.groupEnd();// create widget with specified options
instance.mywidget('destroy');
console.group();var opts = {field1: 'specified',function1: function () {console.log('specified option function1');},
};
instance.mywidget(opts); 
instance.mywidget('printOptions');console.log('-------------');
instance.mywidget(opts); console.groupEnd();// modify options
console.group();instance.mywidget('option', 'field1', 2);
instance.mywidget('printOptions');console.groupEnd();
 

打出的日志如下:

image

日志分为三大块。

第一块是不使用options来初始化,可以看到直接使用定义里默认的options,是不调用_setOption的。

第二块是使用options来初始化,这一块做了两个实验(日志中用--------将两块分隔),第一个实验是完全重建(_create, _init),从日志可以看到并没有调用_setOption;第二个实验只是重新初始化(_init),用的options都一样,从日志可以看到它调用了_setOption,且在_init之前调用的。

第三块不是初始化,而仅仅是修改option值,可以清楚看到调用了_setOption。

何时会调用_setOption的结论:

1. 像instance.mywidget('option', 'field1', 2); 这样显式设置option时。

2. 带着options初始化时:

如果实例不存在,即需要调用_create,则不调用_setOption;

如果实例已存在,仅需要调用_init,则会在调用_init之前调用_setOption。

_trigger

注意这个_trigger是jQueryUI widget factory里的,和jQuery里$.fn命名空间下的trigger函数不是一个东西(后者不带下划线)。

_trigger一般用来回调用户传入options的callback。

在插件内部调用_trigger(‘myEvent’)即相当于调用options里面的myEvent这个回调函数。

要改动options里的event handler应该怎么做呢?不要使用bind/unbind,而是去修改options:

// bind (overwrite, not add event handler)
mw.myWidget('option', 'myEvent', function (event, ui) {console.log('new implement');
});
// unbind
mw.myWidget('option', 'myEvent', null);

总结一下:

this._trigger(‘eventName’)是widget特有的,用于调用options里定义的callback。

this.element.trigger(‘eventName’)是jQuery的,可参考jQuery的事件的用法。(其中this.element是表示该插件的jQuery对象)

一个_trigger的样例:

// 模板
this._trigger( "callbackName" , [eventObject], [uiObject] )

callbackNameThe name of the event you want to dispatcheventObject(Optional)An (mocked) event object. _trigger wraps this object and stores it in event.originalEventThe user receives an object with event.type == this.widgetEventPrefix + "eventname"uiObject(Optional)An object containing useful properties the user may need to access.Protip: Use a method like ._uito generate objects with a consistent schema.

// 调用样例
this._trigger( "hover", e /* e.type == "mouseenter" */, { hovered: $(e.target)});
// The user can subscribe using an init option
$("#elem").filterable( { hover: function(e,ui) { } } );
// Or with traditional event binding/delegation
$("#elem").bind( "filterablehover" , function(e,ui) { } );

转载于:https://www.cnblogs.com/dc10101/archive/2012/05/03/2481004.html

相关文章:

mail 发送email

&#xff08;一&#xff09;首先安装ssmpt和mailutils&#xff1a; sudo apt-get install ssmtp mailutils &#xff08;二&#xff09;接下来编辑配置文件sudo gedit /etc/ssmtp/ssmtp.conf rootYOUR_PERSONAL_MAILDOMAIN mailhubsmtp.gmail.com:465 rewriteDomaingmail.com A…

C语言中字符型在计算机中的存储

一. 字符型的分类和表示范围 char&#xff1a;是有符号还是无符号数视编译器而定&#xff0c;一般为有符号数&#xff0c;下文把它全部当成有符号数进行讨论 表示范围&#xff1a;32位和64位机器上均是一个字节&#xff0c;所以是八个bit位&#xff0c;最高位为符号位之后&…

python中正确的表达式_python中如何正确使用正则表达式的详细模式(Verbose mode expression)...

简单介绍正则表达式并不是Python的一部分。正则表达式是用于处理字符串的强大工具&#xff0c;拥有自己独特的语法以及一个独立的处理引擎&#xff0c;效率上可能不如str自带的方法&#xff0c;但功能十分强大。得益于这一点&#xff0c;在提供了正则表达式的语言里&#xff0c…

ASP.NET中 RequiredFieldValidator(非空验证)的使用

ylbtech-ASP.NET-Control-Validator: RequiredFieldValidator(非空验证)的使用ASP.NET中 RequiredFieldValidator(非空验证)的使用。 1.A,运行效果返回顶部 登录 RequiredFieldValidator&#xff1a;非空验证重要的属性&#xff1a;1,ControlToValidate&#xff1a;要验证的控件…

5013.FortiGate企业级硬件防火墙Demo演示文档

FortiGate企业级硬件防火墙Demo演示文档 语言&#xff1a;英文类型&#xff1a;Demo大小&#xff1a;2MB格式&#xff1a;WEB摘要&#xff1a;和真实的硬件防火墙操作界面一模一样的&#xff0c;非常实用&#xff01;可以通过这些界面了解到在配置硬件防火墙时需要配置哪些参数…

下拉列表JComboBox,列表框JList

1、下拉列表JComboBox public class Demo extends JFrame {public Demo() {setBounds(100, 100, 200, 100);setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);Container c getContentPane();c.setLayout(new FlowLayout()); // JComboBox cbbnew JComboBox();…

C语言中整型在计算机中的存储

一 . 整型的表示 1.字面值后面加上L(l)表示long长整型 2.字面值后面加上U(u)表示usigned整型值 3.十进制123 ... 4.八进制&#xff0c;以0开头&#xff0c;如0123&#xff0c;0754 ... 5.十六进制&#xff0c;以0x开头&#xff0c;如0xF32 ... 二 .整型的分类和表示范围 ch…

多个前端项目放在一个git好还是_前端工作流

没有规矩不成方圆&#xff0c;如果一个项目只有你一个人在维护&#xff0c;那么你不需要担心很多问题&#xff0c;因为你对它心知肚明&#xff0c;但同时一个人的力量无法支撑起来大型项目。更多时候&#xff0c;我们需要与其他人合作&#xff0c;共同把项目推进&#xff0c;这…

hadoop上的pageRank算法

简单的pageRank实现参考&#xff1a;http://wlh0706-163-com.iteye.com/blog/1397694 较为复杂的PR值计算以及在hadoop上的实现&#xff1a;http://deathspeeder.is-programmer.com/posts/31349.html pageRank算法的基本思想是&#xff1a;网页的热门程度依赖指向它的网页的热门…

【11平台天梯】【原理分析】11平台天梯原理分析

写作缘由 (Elo Ratings) ELO排名制度是当今对弈水平评估的公认的权威方法。它最初由物理学教授 Arpad Elo 创立&#xff0c;故命名为埃罗排名。埃罗排名最早应用于国际象棋和围棋&#xff0c;目前已广泛用于国际象棋、围棋、足球、篮球等运动。ELO算法先是在网游WOW取得了成功&…

PAT Basic 1072

1072 开学寄语 下图是上海某校的新学期开学寄语&#xff1a;天将降大任于斯人也&#xff0c;必先删其微博&#xff0c;卸其 QQ&#xff0c;封其电脑&#xff0c;夺其手机&#xff0c;收其 ipad&#xff0c;断其 wifi&#xff0c;使其百无聊赖&#xff0c;然后&#xff0c;净面、…

C语言中浮点型在计算机中的存储

一 . 浮点型的存储 在十进制中我们都学习过科学计数法&#xff0c;比如31.4可以用科学计数法表示就是3.14*10^1。浮点型同样是采取科学计数法进行表示的。在计算机中&#xff0c;以二进制数存储&#xff0c;如1011.10用科学计数法的方式可以写成1.01110*2^3&#xff0c;因为浮点…

object-c中管理文件和目录:NSFileManager使用方法

object&#xff0d;c中管理文件和目录&#xff1a;NSFileManager使用方法 对于NSFileManager&#xff0c;文件或目录是使用文件的路径名唯一标识的。每一个路径名都是一个NSString对象&#xff0c;它可以是相对路径名&#xff0c;也可以是完整路径名。 相对路径名是相对于当前目…

python实现ssh登录send_Python实现ssh批量登录并执行命令

局域网内有一百多台电脑&#xff0c;全部都是linux操作系统&#xff0c;所有电脑配置相同&#xff0c;系统完全相同(包括用户名和密码)&#xff0c;ip地址是自动分配的。现在有个任务是在这些电脑上执行某些命令&#xff0c;者说进行某些操作&#xff0c;比如安装某些软件&…

传Exchange 15将于今年9月发布

Microsoft Exchange Conference &#xff08;简称MEC&#xff09;是微软公司所举办的有关Exchange Server软件的主题会议&#xff0c;但它在过去的十年间一直没有举行。今年的9月24-26日&#xff0c;微软将在佛罗里达州重新启动MEC并展示Exchange 15。根据ZDNet报道&#xff0c…

Django进阶之session

基于cookie做用户验证时&#xff1a;敏感信息不适合放在cookie中 session依赖cookie session原理 cookie是保存在用户浏览器端的键值对 session是保存在服务器端的键值对 session服务端中存在的数据为&#xff1a; session {随机字符串1&#xff1a;{用户1的相关信息}随机字符…

python画美女代码_教你用python爬取网站美女图(附代码及教程)

我前几篇文章都是说一些python爬虫库的用法&#xff0c;还没有说怎样利用好这些知识玩一些好玩的东西。那我今天带大家玩好玩又刺激的&#xff0c;嘻嘻&#xff01;对了&#xff0c;requests库和正则表达式很重要的&#xff0c;一定要学会&#xff01;一定要学会&#xff01;&a…

Python基础学习3

6 模块和包 (1) 命名以.py结尾的文件就是Python模块 Python的包就是一个文件夹&#xff0c;至少有还有一个__init__.py的文件 包中可以有文件夹&#xff0c;文件夹中可以有包 (2) 文件的导入 每使用一个变量名或者函数时&#xff0c;就需要导入另一个文件 例&#…

CSS伪类 选择器

一、伪类:active/*被激活的元素*/:focus/*拥有键盘输入焦点的元素*/ :hover/*鼠标悬浮在元素上方时*/ :link/*未被访问的链接*/ :visited/*已被访问的链接*/ :first-child/*元素的第一个子元素*/ :lang/*带有指定 lang 属性的元素*/ CSS执行顺序是&#xff1a;lvcha link :hove…

svn中的revert和update

svn中的revert和update今天有人问到revert和update的问题。刚开始还真被问住了。因为感觉revert和update都可以将本地的copy更新到以前的一个版本&#xff0c;会有什么不同呢&#xff1f;查了些资料&#xff0c;并做了个试验&#xff0c;终于发现了它们的不同。假设当前最新的版…

BOM 浏览器对象模型和DOM 文档对象模型

浏览器对象模型BOM 1. 浏览器对象模型介绍 BOM(Browser Object Model) 是指浏览器对象模型&#xff0c;是用于描述这种对象与对象之间层次关系的模型&#xff0c;浏览器对象模型提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。BOM由多个对象组成&#xff0c;其中代表…

上交三月月赛[SJTU] 1106 sudoku

题目大意&#xff1a;给出一道数独题&#xff0c;判断该数独是否有解且有唯一解。 解题思路&#xff1a; 由前几题的难度得&#xff0c;此题的难度不会太过分&#xff0c;所以简单暴力就可以了&#xff0c;40ms用时一本满足。 简单地讲一下具体的实现&#xff0c;从左上开始从左…

C语言-三子棋游戏

C语言中用写头文件的方式写了一个三子棋游戏 1.测试函数text.c #define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> #include<string.h> #include<stdlib.h> #include<time.h> #include"chess.h"void menu() {printf("*************…

取余运算怎么算_TensorFlow2.0(2):数学运算

点击“机器学习算法与Python实战”&#xff0c;“置顶”公众号重磅干货&#xff0c;第一时间送达TensorFlow2.0(1)&#xff1a;基本数据结构——张量1 基本运算&#xff1a;(、-、*、/、//、%) 基本运算中所有实例都以下面的张量a、b为例进行&#xff1a;import tensorflow as …

xen二进制安装

需要几台机器做集群测试,目前只有一台机器所以用xen来虚拟化几台机器出来 系统: centos5.6 安装xen yum install kernel-xen xen修改grub /boot/grub/grub.conf将default1改为default0 default0 timeout5 splashimage(hd0,0)/grub/splash.xpm.gz hiddenmenu title CentOS (2.6.…

python模块之json,pickle

序列化是指把内存里的数据转变成字符串&#xff0c;以使其能保存到硬盘上或者通过网络输送到远程。 序列化的两个模块&#xff1a; json:只能把python中的int/str/list/tuple/dict类型的数据&#xff0c;可以在不同的语言之间传递数据。Python和JavaScript数据对应关系&#xf…

关于如何在pc端使用github

http://www.bcwhy.com/thread-17636-1-1.html转载于:https://www.cnblogs.com/glgl2424/archive/2013/03/13/2956944.html

Python爬虫1-Scrapy环境的安装

一. Scrapy环境的安装 1. Scrapy各平台支持情况 除了python3在Windows下不支持外&#xff0c;其余&#xff08;Linux&#xff0c;Mac&#xff09;均支持 2. 安装miniconda (1)建议使用Python2&#xff0c;用miniconda安装scrapy (2)miniconda时Python环境管理工…

汉字笔画数据_统计学原理 数据的预处理

数据审核数据审核—原始数据(raw data)完整性审核应调查的单位或个体是否有遗漏所有的调查项目或变量是否填写齐全准确性审核数据是否真实反映实际情况&#xff0c;内容是否符合实际数据是否有错误&#xff0c;计算是否正确等数据审核—二手数据(second hand data)适用性审核弄…

SqlServer时间函数的使用例子整理

为什么80%的码农都做不了架构师&#xff1f;>>> 整理SqlServer2008的时间函数如下&#xff1a; 1.获取系统时间 select getdate(); --2012-05-06 22:26:49.950 select current_timestamp; --2012-05-06 22:26:49.950 select getutcdate(); --20…