-1

我会尽量简单:

我在 jqueryui 的帮助下编写了一个 jquery 小部件(转到 themeroller,下载一个主题,将其解压缩,然后在该文件development-bundle夹中您会找到一个名为 的文件夹ui,然后仅包含jquery.ui.widget.js此示例以运行):

<!doctype html>
<html>
<head>
<meta charset=utf-8>
<title>jQuery widget construction & Events</title>
<style>
  h1 {
     color: #808080;
  }
  h1:hover {
     color: #000000;
     text-decoration: none;
     cursor: pointer;
  }
  a {
     color: #808080;
     background-color: #CCFF33;
  }
</style>
</head>
<body>

<h1>Click Me</h1>

<div class=content>
<p>
<a href="http://speckyboy.com/2010/01/20/25-tutorials-and-resources-for-learning-jquery-ui/">spekyboy</a>
</p>
<p>
<a href="http://www.learningjquery.com/">learning jquery</a>
</p>    
</div>

<script src="../jquery-1.7.1.js"></script>
<script src="../jquery.ui.widget.js"></script>

<script>
////////////////////////Plugin Creation (Widget Factory)////////////////////////
///////////////////////////mycompany.linkLocation///////////////////////////////
(function( $ ) {
//1. use jQuery.widget() method, the Widget factory, to create plugins
//--------------------------------------------------------------------
$.widget( "mycompany.linkLocation", {
  //2. widget properties "foreground" and "background" (see docs)
  //-------------------------------------------------------------
  options: {
     color: "black",
     "background-color": "transparent",
     done: false,
     //3. a callback from the relevant widget event: linkLocation_onapply (see docs)
     //-----------------------------------------------------------------------------
     //where does this refers to (???)
     //evt refers to the custom jquery event object
     _onapply: function(evt, options){
        var attrs='';
        for(prop in this)
           attrs+=prop+', ';
        alert('from _onapply, this:\n'+attrs);
        attrs='';
        for(prop in evt)
           attrs+=prop+'='+evt[prop]+'\n';
        alert('from _onapply 1st arg, evt:\n'+attrs);
        //4. where is the reference to widget linkLocation for evt.target?
        //----------------------------------------------------------------
        $(evt.target).css(options);
     }
  },
  //5. used during construction by the Widget Factory (see docs)
  //------------------------------------------------------------
  //this refers to the object built by the Widget Factory
  _create: function() {
  },
  //6. used after initialization (see docs)
  //---------------------------------------
  //called as $("selector").widgetname("option", option_object)
  //or,
  //$("selector").widgetname("option", "key", "value")
  //this refers to the object built by the Widget Factory
   _setOption: function(key, value){
     this.options[ key ] = value;
  },
  //7. public method apply()
  //------------------------
  //this refers to the object built by the Widget Factory
  apply: function(evt){
     if(!this.options.done){
        //create a jquery object that wraps a specific dom element accessed
        //through the this.element provided by the Widget Factory
        var $this = $(this.element);
        this._css($this);
        ////////////////////////////////////////////////////////////////////////////
        //8. maybe one reason we done all these: add memory and execute only once!//
        ////////////////////////////////////////////////////////////////////////////
        //--------------------------------------------------------------------------
        this.options.done = true;
        //9. if apply() is called once then, _onapply() is called once
        //------------------------------------------------------------
        //event linkLocation_onapply will trigger method _onapply(), see docs
        this._trigger("_onapply", evt, {color: "white", "background-color": "purple"});
     }
  },
  //10. a private method _css()
  //--------------------------
  //this refers to the object built by the Widget Factory
  _css: function($elem){
     $elem.css({
        "background-color": this.options.background,
        "color": this.options.foreground
     });
  }
});
}( jQuery ));
//11. user overwites public property: this.options
//------------------------------------------------
//for the objects created by the Widget Factory
var options2 = {
   color: "blue",
   "background-color": "yellow"
};
//12. construct an object for every <a> element using the Widget Factory
$( "a" ).linkLocation(options2);
//13. call widget apply() methods
//-------------------------------
$('h1').on('click', function(evt) {
   //14. the jquery $(h1) object
   var attrs='';
   for(prop in this)
      attrs+=prop+', ';
   alert('From h1 tag onclick event, this:\n'+attrs);
   $( "a" ).linkLocation("apply").on("linklocation_onapply", 
      //15. never executed???
      function(evt, data){
         attrs='';
         for(prop in data)
            attrs+=prop+': '+data[prop]+'\n';
         alert('From linklocation_onapply event function, data:\n'+attrs);
      }
   );
});
</script>

</body>
</html>

(请在代码注释中查看我的数字)现在,我们所做的就是创建(12)一个带有一些选项(2)的小部件,它什么都不做(5)。用户可以在施工期间更改默认选项(11)。用户可以调用公共方法apply() (7)以根据小部件选项更改锚前背景颜色,但我们还想定义一个将在自定义 jquery 事件(9)上触发的回调。

每次用户单击 h1 标记(13)时,方法apply() (7)会从每个被调用linkLocation并附加到锚元素(12)的小部件中执行, 但只执行一次(我们将代码放在 if..else 中)。正如我们所说,方法apply()更改锚点颜色并触发回调函数。

我的问题:

a) 是this在回调_onapply() (3)实际调用我的小部件的公共方法的jquery 对象,正如我们在来自评论(14)的消息中看到的那样?消息是:

From h1 tag onclick event, this:
jQuery17102845835909852654, align, click, focus, blur, title, lang, dir, dataset, 
itemScope, itemType, itemId, itemRef, itemProp, properties, itemValue, hidden, 
tabIndex, accessKey, ...

接下来是我们的小部件消息:

from _onapply, this:
jQuery17102845835909852654, toString, href, target, download, ping, rel, hreflang, 
type, text, coords, charset, name, rev, shape, protocol, host, hostname ...

from _onapply 1st arg, evt:
type=linklocation_onapply
timeStamp=1382545296011
jQuery17102845835909852654=true
...

如果你比较你会发现它_onapply有额外的属性——为什么会这样

toString, href, target, download, ping, rel, hreflang, type, text, coords, charset,
name, rev, shape, protocol, host, hostname, port, pathname, search, hash

b) 为什么我在评论(15)处的事件处理程序从未被执行?

jQuerync) jquery 对象属性中 n=number的这个总是变化的属性是什么?看起来 jquery 不是一个单例对象,当我们想要在 dom 元素状态上拥有内存时,就像小部件对象的情况一样,这似乎是一种束缚;它们存储在一个 jquery 对象中,但是当它不断克隆自身时是哪一个?

和 d) 正如您在评论(4)linkLocation中看到的那样,对于触发我的自定义事件的特定元素,我的小部件的引用在哪里?

真的,找不到图书馆承诺的抽象......继续搜索源代码以寻找答案......谢谢。

4

1 回答 1

0

在寻找答案后,我得出以下结论:

对于 Qa)_onapply()小部件的函数在options内部更改执行上下文,因为它已分配给小部件的连接元素,因此,它是元素的引用

对于 Qb) 事件系统实现了可观察模式;某人扮演被他人观察的角色,这就是小部件。一个可观察对象不能响应它自己的信号(见注释(15))所以,我们需要观察者来完成这项工作,即将事件处理程序附加到其他元素上,以处理由小部件发出信号的特定事件,你有它,一个可观察对象的响应(那是带有代码的新注释(16))。

没有说或写的是,我们可以在小部件构造中拥有两种类型的可观察对象:一种使用函数的正式的this.element.trigger(eventtype, data)- 一个通用触发器 - 以及一种被称为this._trigger(eventtype, event, data)并用于调用函数的特定对象附加到小部件并同时发出信号,可观察量 - 一个选项触发!

在评论(9)(11)下,我实现了这两种类型。奇怪的options trigger是它能够在namespacewidgetname没有连接点或其他任何东西的情况下调用和发出事件命名的信号。

根据调用函数的位置, anoptions trigger分为两个子类别: -construction options trigger调用构造中定义的函数和 -user options trigger调用用户定义的函数并扩展小部件的语义,即使开发人员很难理解它的可用性也可以'不预测用户的扩展。

对于 Qc) 和 Qd) 我觉得回答不安全...

对于关于 jquery 对象和小部件之间连接的标题问题,答案是没有,因为小部件与事件系统等元素紧密相关,而 jquery 充当中间查找元素和附加属性......

让我们测试一下:

<!doctype html>
<html>
<head>
<meta charset=utf-8>
<title>Custom Effect Methods</title>
<style>
  h1 {
     color: #808080;
  }
  h1:hover {
     color: #000000;
     text-decoration: none;
     cursor: pointer;
  }
  a {
     color: #808080;
     background-color: #CCFF33;
  }
</style>
</head>
<body>

<h1>Click Me</h1>

<div class=content>
<p>
<a href="http://speckyboy.com/2010/01/20/25-tutorials-and-resources-for-learning-jquery-ui/">spekyboy</a>
</p>
<p>
<a href="http://www.learningjquery.com/">learning jquery</a>
</p>    
</div>

<script src="../jquery-1.7.1.js"></script>
<script src="../jquery.ui.widget.js"></script>

<script>
////////////////////////Plugin Creation (Widget Factory)////////////////////////
///////////////////////////mycompany.linkLocation///////////////////////////////
(function($, window, document, undefined){
//1. use jQuery.widget() method, the Widget factory, to create plugins
//--------------------------------------------------------------------
$.widget( "mycompany.linkLocation", {
  //2. widget properties "foreground" and "background" (see docs)
  //-------------------------------------------------------------
  options: {
     that: this,
     color: "black",
     "background-color": "transparent",
     done: false,
     //3. a callback from the relevant widget event: linkLocation_onapply (see docs)
     //-----------------------------------------------------------------------------
     //this refers to the element referencing the plugin (element.data property?)
     //evt refers to the custom jquery event object
     _onapply: function(evt, options){
        //4. where is the reference to widget linkLocation for evt.target?
        //----------------------------------------------------------------
        $(evt.target).css(options);
     }
  },
  //5. used during construction by the Widget Factory (see docs)
  //------------------------------------------------------------
  //this refers to the object built by the Widget Factory
  _create: function() {
  },
  //6. used after initialization (see docs)
  //---------------------------------------
  //called as $("selector").linkLocation("option", option_object)
  //or,
  //$("selector").linkLocation("option", "key", "value")
  //this refers to the object built by the Widget Factory
   _setOption: function(key, value){
     this.options[ key ] = value;
  },
  //7. public method apply()
  //------------------------
  //this refers to the object built by the Widget Factory
  apply: function(evt){
     if(!this.options.done){
        //create a jquery object that wraps a specific dom element accessed
        //through the this.element provided by the Widget Factory
        var $this = $(this.element);
        this._css($this);
        ////////////////////////////////////////////////////////////////////////////
        //8. maybe one reason we done all these: add memory and execute only once!//
        ////////////////////////////////////////////////////////////////////////////
        //--------------------------------------------------------------------------
        this.options.done = true;
        //9. if apply() main code is executed once then, 
        //onapply() & trigger are executed only once
        //------------------------------------------
        //(!!!construction options trigger!!!) register observers for event linkLocation_onapply
        //--------------------------------------------------------------------------------------
        this._trigger("_onapply", evt, {color: "white", "background-color": "purple"});
        //(!!!user options trigger!!!) register observers for event linkLocation_onuserapply
        //----------------------------------------------------------------------------------
        this._trigger("_onuserapply", evt, {color: "white", "background-color": "orange"});
        //(!!!general trigger!!!) register observers for the event shown
        //---------------------------------------------------------------
        this.element.trigger("mycompany.linkLocation.customevent", this.options);
     }
  },
  //10. a private method _css()
  //--------------------------
  //this refers to the object built by the Widget Factory
  _css: function($elem){
     $elem.css({
        "background-color": this.options.background,
        "color": this.options.foreground
     });
  },
  _destroy: function() {
  }
});
}(jQuery, window, document));
//11. user overwites public property: this.options
//------------------------------------------------
//for the objects created by the Widget Factory
var options2 = {
   color: "blue",
   "background-color": "yellow",
   //a user supplied function that will trigger a custom event
   _onuserapply: function(evt, options){
      $(evt.target).css(options);
   }
};
//12. construct an object for every <a> element using the Widget Factory
var widgets = $( "a" ).linkLocation(options2);
//13. call widget apply() methods
//-------------------------------
$('h1').on('click', function(evt){
   //14. at this point this refers to h1 element
   //...
   $( "a" ).linkLocation("apply").on("linklocation_onapply", 
      //15. an observable cannot catch it's own signals!!!
      function(evt, data){
         attrs='';
         for(prop in data)
            attrs+=prop+': '+data[prop]+'\n';
         alert('From linklocation_onapply on observable\'s event function, data:\n'+attrs);
      }
   );
});
//16. register observers on widget mycompany.linkLocation
$("div.content").on({
   //an observer to a custom event mycompany.linkLocation.customevent
   "mycompany.linkLocation.customevent": function(evt, data){
      var attrs='';
      for(prop in data)
         attrs+=prop+': '+data[prop]+'\n';
      alert('From mycompany.linkLocation.customevent event on div.content event function, data:\n'+attrs);
   },
   //an observer to a custom event linklocation_onapply
   "linklocation_onapply": function(evt, data){
      var attrs='';
      for(prop in data)
         attrs+=prop+': '+data[prop]+'\n';
      alert('From linklocation_onapply event on div.content event function, data:\n'+attrs);
   },
   //an observer to a custom event linklocation_onuserapply
   "linklocation_onuserapply": function(evt, data){
      var attrs='';
      for(prop in data)
         attrs+=prop+': '+data[prop]+'\n';
      alert('From linklocation_onuserapply event on div.content event function, data:\n'+attrs);
   }
});
</script>

</body>
</html>
于 2013-10-25T18:10:12.500 回答