惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
Stack Overflow Blog
Stack Overflow Blog
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
T
The Blog of Author Tim Ferriss
博客园 - 叶小钗
N
Netflix TechBlog - Medium
腾讯CDC
C
Check Point Blog
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
S
SegmentFault 最新的问题
F
Fortinet All Blogs
美团技术团队
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
F
Full Disclosure
Recorded Future
Recorded Future
D
DataBreaches.Net
博客园 - 【当耐特】
Martin Fowler
Martin Fowler
J
Java Code Geeks
I
InfoQ
Y
Y Combinator Blog
A
About on SuperTechFans
AI
AI
爱范儿
爱范儿
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Forbes - Security
Forbes - Security
W
WeLiveSecurity
M
MIT News - Artificial intelligence
雷峰网
雷峰网
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
Schneier on Security
Schneier on Security
The GitHub Blog
The GitHub Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
GRAHAM CLULEY
Know Your Adversary
Know Your Adversary
Latest news
Latest news
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Docker
Recent Commits to openclaw:main
Recent Commits to openclaw:main
量子位
V2EX - 技术
V2EX - 技术
Project Zero
Project Zero

博客园 - Roamman

RRAS Access一些问题 临时表的一个用法 ConnectionString Microsoft SQL Server 错误代号: 15535 解决方法 百度也开源 位运算 之(1) 按位与(AND)& 操作 托管调试助手报错 类型初始值设定项引发异常 js 的开发效率 window.showModalDialog 以及window.open用法简介 Emterprise Library 学习地址 Web 开发与设计之 Google 兵器谱 Web 开发与设计之 Google 兵器谱 Web 开发与设计之 Google 兵器谱 Web 开发与设计之 Google 兵器谱 Web 开发与设计之 Google 兵器谱 Jquery Ajax时 error处理 之 parsererror jQuery工作原理解析以及源代码示例
jQuery Widget 开发指南
Roamman · 2010-02-02 · via 博客园 - Roamman

原文:http://bililite.com/blog/understanding-jquery-ui-widgets-a-tutorial/

由于翻译后不能使用HTML和SCRIPT所以演示部分就不能看到了,请参照原文。

写这篇文章的目的是为了让我理解并开发出我自己的Widgets,同时我也希望这篇文章能对其他人也有帮助。Widget让我说就是一种用户界面元素,类似于按钮或者像复杂的DatePicker(日期选择控件)。但这一概念对于jQuery,更确切的说是一个类。这个类的成员与一些HTML元素相关,比如Draggable和Sortable。当然不是所有Widget都使用$.widget,例如datePicker就没有使用。

插件:修改元素

让我们用一个带CSS类的P元素作为目标举个例子。

<p class="target">This is a paragraph</p>

我们把它变绿:

$(".target").css({"background":'green'});

然后我们需要将这一功能更通用化:

$.fn.green = function() {return this.css({background: 'green'})}

上面的代码是我们可以在任意的选中元素上产生效果,但他没有让我们保持和某个元素的关联。例如如果我们需要制作一个恢复背景的功能,哪么我们必须确定他的初始颜色。如果要设计一个Darker(),我们就必须知道元素现在是什么颜色。

保持插件状态

我们可以创建一个与某元素管理单的对象:


 element.myobject = new Myobject({'target': element})

$.fn.green2 = function() {

               return this.each(function(){

                        if (!this.green) this.green = new Green(this); // associate our state-keeping object with the element

                            this.green.setLevel(15);

                  });

           };

$.fn.off = function() {

              return this.each(function(){

                         if (this.green) this.green.setLevel(16);

                             delete this.green; // recover the memory

                });

            };

$.fn.darker = function() {

              return this.each(function(){

                       if (this.green) this.green.setLevel(this.green.getLevel()-1);

               });

           };

$.fn.lighter = function() {

             return this.each(function(){

                    if (this.green) this.green.setLevel(this.green.getLevel()+1);

              });

          };

function Green(target){

greenlevels = ['#000','#010','#020','#030','#040','#050','#060','#070','#080','#090','#0a0','#0b0','#0c0','#0d0','#0e0','#0f0','#fff'];

this.target = target; // associate the element with the object

this.level = 0;

this.getLevel = function() { return this.level; }

this.setLevel = function(x) {

this.level = Math.floor(Math.min(greenlevels.length-1, Math.max(0,x)));

this.target.css({background: greenlevels[this.level]});

}

};

但是上面这种方式使得$.fn命名空间中出现了很多函数。我们也可以在该命名空间内再创建一个命名空间,但一般的设计思路使用一个字符串来调用相应的函数,即我们可以使用类似element.green2("darker")来调用darker()方法:


$.fn.green2 = function(which){

        return this.each(function(){

           if (which === undefined){ // initial call

                if (!this.green) this.green = new Green($(this)); // associate our state-keeping object with the element

                      this.green.setLevel(15);

                }else if (which == 'off'){

                        if (this.green) this.green.setLevel(16);

                        delete this.green

               }else if (which == 'darker'){

                      if (this.green) this.green.setLevel(this.green.getLevel()-1);

               }else if (which == 'lighter'){

                     if (this.green) this.green.setLevel(this.green.getLevel()+1);

              }

          });

  };

function Green(target){

greenlevels = ['#000','#010','#020','#030','#040','#050','#060','#070','#080','#090','#0a0','#0b0','#0c0','#0d0','#0e0','#0f0', '#fff'];

this.target = target; // associate the element with the object

this.level = 0;

this.getLevel = function() { return this.level; }

this.setLevel = function(x) {

this.level = Math.floor(Math.min(greenlevels.length-1, Math.max(0,x)));

this.target.css({background: greenlevels[this.level]});

}

};

插件与对象关联所带来的问题
上面的方式能够方便的写出程序,但是也带来了循环引用和可能的内存漏洞。浏览器对于Javascript和Dom元素是使用不同的垃圾回收方式,上面的引用方式可能就会带来问题,使得回收不能正常进行。
我们同时也要注意,在我们开发插件是也要注意内存的回收。
jQuery用$.fn.data解决了这一问题:
 $(element).data('myobject', new Myobject({'target': element}))
但是,这样做的同时又带来了其他的问题,我们需要做很多“额外”的工作,这些工作与程序逻辑毫无关系,重复而无用。所以重复实现这一功能,需要抽象出来减少工作。
解决问题:$.widget
这就是$.widget出现的原因。它使得插件中的Javascript类的单个实例与每个元素相关联,这样我们在与对象进行交互操作元素的时候就不会带来内存绣楼的问题。
同上面一样,你还是需要创建类的构造函数。与之不同的是,我们需要一个包含了相关方法的“原型”。同时也有一些变化,如:_init()函数在构造是调用,destroy()方法在析构是调用。这两个函数都是预先定义的,不过你可以覆盖。element和上面我们的target是与类相关的jQuery对象。
Widget中所有已“_”开头的方法都属预定义似有形函数,外部不能调用。 
 var Green3 = { 
_init: function() { this.setLevel(15); }, 
 greenlevels: ['#000','#010','#020','#030','#040','#050','#060','#070','#080','#090','#0a0','#0b0','#0c0','#0d0','#0e0','#0f0', '#fff'], 
 level: 0, 
 getLevel: function() { return this.level; }, 
 setLevel: function(x) { this.level = Math.floor(Math.min(this.greenlevels.length-1, Math.max(0,x))); 
 this.element.css({background: this.greenlevels[this.level]}); }, 
 darker: function() { this.setLevel(this.getLevel()-1); }, 
 lighter: function() { this.setLevel(this.getLevel()+1); }, 
 off: function() {this.element.css({background: 'none'}); 
 this.destroy(); // use the predefined function } 
 }; 

上述代码即就是整个程序逻辑,使用下面代码生成插件:

$.widget("ui.green3", Green3); // create the widget

转载:http://terry.blog.35.cn/2009/07/12/jquery-widget-%E5%BC%80%E5%8F%91-tutorial-%E7%BF%BB%E8%AF%91%E7%89%88/