【问题标题】:Custom event in jQuery that isn't bound to a DOM element?jQuery中未绑定到DOM元素的自定义事件?
【发布时间】:2009-10-12 08:13:02
【问题描述】:

我很好奇是否可以在 jQuery 中创建一个未绑定到 DOM 元素的自定义事件。

我更喜欢 jQuery 而不是 YUI,但在 YUI 中我喜欢一件事,那就是创建自定义事件并能够在以后订阅它们。

例如,这会创建一个绑定到变量而不是 DOM 元素的事件:

var myevent = new YAHOO.util.CustomEvent("mycustomevent");

我为 jQuery 阅读的所有示例和文档都需要类似以下内容:

$('body').bind('mycustomevent', function(){
    //do stuff
});

【问题讨论】:

  • 我猜 jquery 根本不会理解 'mycustomevent' 和 YUI 事件。但是您可以尝试使用指针:bind(myevent, ..
  • 我认为,与 Django 类似,JQuery 中有一些最佳实践。首先,插件。您可以将自定义事件创建为外部类,作为 JQuery 的插件,并且您可以使用任何选择器简单地将事件绑定到您的元素,例如 $("#myDiv").myPlugin("does a lot of stuff ") 有几种方法可以做到这一点,但你应该首先确认你到底需要什么。你能详细说明一下吗?我可以尝试给你更准确的评论)thx
  • 嗨!他们接受的答案不正确(或不再正确)。你能不能把我接受的答案改成我的?

标签: jquery events


【解决方案1】:

您可以在 jQuery 中像这样触发自定义全局事件:

jQuery.event.trigger('mycustomevent', [arg1, arg2, arg3]);

这些将触发任何元素。

由于 jQuery 是围绕 DOM 对象构建的,因此您必须将事件绑定到 DOM 对象。您可能也可以找到某种方法来绑定没有元素的事件(您确实做到了),但这不是受支持的方法。

正如您在自己的答案中所写,如果您不想将事件绑定到单个页面元素,则可以将其绑定到全局 DOM 对象:

$(document).bind('mycustomevent', function (e, arg1, arg2, arg3) { /* ... */ });

【讨论】:

【解决方案2】:

根据a comment by John Resig支持通过jQuery绑定事件到自定义对象:

没有特别的原因说明它没有被记录(除了它对大多数用户来说相当非传统) - 但是是的,我们支持它并对其进行单元测试。

所以这行得通:

var a = {foo: 'bar'};
$(a).on('baz', function() {console.log('hello')});
$(a).triggerHandler('baz');
>>> 'hello'

大多数用户需要triggerHandler(),而不是trigger()。如果使用.trigger("eventName"),它将在对象上查找“eventName”属性,并在执行任何附加的jQuery 处理程序后尝试执行它(Source)。

编辑(2017 年 2 月 28 日):

在大型代码库中使用这种模式大约 2 年之后,我可以证明这是一个坏主意。这些自定义事件会导致难以理解的数据流。更喜欢回调。

【讨论】:

  • 愚蠢的问题:它有没有被记录在案的原因?不应该使用吗?可以在较新的版本中删除/修改它吗?我想知道是否应该使用它来支持其他子发布库,例如EvenEmitter
【解决方案3】:

对于未来的读者来说,这样做相当简单。在发布我的问题后,我做了进一步的研究。不幸的是,其他评论者都不正确。

为了绑定自定义事件:

$().bind('mycustomevent', function(){
    //code here
});

此外,您可以将数据构建到稍后可访问的事件对象中:

$({mydata:'testdata'}).bind('mycustomevent',function(){
    //code here
});

【讨论】:

  • 您应该知道,使用$(),您仍然将其绑定到一个DOM 对象($()$(document) 相同)。 $({}) 有效,但您应该知道它有效,因为 jQuery 从不检查它是否是 DOM 对象。它仍然用一个 jQuery 对象包装它,该对象具有诸如 append(...) 之类的方法,如果被调用,它将停止你的脚本。此外,包装非 DOM 对象的行为是未定义的,将来可能会改变。所以我仍然坚持我的回答,并建议您将其绑定到 $(document) 而不是 JavaScript 对象。
【解决方案4】:

在 jQuery 1.4.4 中已移除与非 dom 元素的绑定。

【讨论】:

  • 也许,他的意思是纯 JavaScript 对象?
【解决方案5】:

您仍然可以使用 jQuery 任意触发和响应事件,即使您不知道要将它们附加到哪个元素。只需在您的文档中创建一个“接收者”元素,您可以将所有自定义事件绑定到该元素。这使您可以在一个地方为所有非特定于元素的事件管理事件处理逻辑。

$(document).ready(function() {

  $(body).append('<div id="receiver">');

  $("#receiver").bind("foo_event", function () {
    // decide what to do now that foo_event has been triggered.
  });

  $("#some_element").click(function() {
    $("#receiver").trigger("foo_event");
  });

});

【讨论】:

  • 我认为这是个坏主意。如果你真的想要一些元素来附加事件,为什么不使用$('body')$(document)
  • 这只是一个有效的约定。与使用文档或正文相比,我更喜欢它,因为它有点像一个无菌的事件交换所——我知道其中的一切,并且不太可能意外发生一些不想要的坏事。你能解释一下为什么你认为这是个坏主意吗?
【解决方案6】:

jQuery Callbacks 提供了一种实现独立于 DOM 的发布-订阅系统的简单方法。

链接页面底部附近的示例代码显示了如何执行此操作。

【讨论】:

    【解决方案7】:

    [编辑]

    这是一个使用以下概念的工作类:

    https://github.com/stratboy/image-preloader

    它只是一个顺序图像预加载器。您可以订阅一堆事件。看看吧。

    [/编辑]

    旧帖:

    这是另一个准系统示例,其中包含 Himanshu P 建议的回调。

    我正在构建一个类,我来自 Mootools,其中类和直接在类中实现的自定义事件(因此不绑定到 DOM 元素)是绝对自然的。所以我尝试了一种解决方法并在下面分享。

      var step_slider;
    
      //sandbox
      ;(function($) {
    
    //constructor
    var StepSlider = function(slider_mask_selector,options) {
    
        //this.onStep = $.Event('step');
        this.options = null;
        this.onstep = $.Callbacks();
    
        this.init();
    }//end constructor
    
    StepSlider.prototype = {
    
        init:function(){
            this.set_events();
        },//end init
    
        set_events:function(){
    
            if(this.options){
                if(this.options.onstep){
                    this.subscribe('step',options.onstep);
                }
            }
    
        },//set_events
    
        subscribe:function(event,action){
            this['on'+event].add(action);
        },
    
        fire_onstep:function(){
            this.onstep.fire({ data1:'ok' });
        }
    
    }//end prototype/class
    
    //--------------------
    
    $(document).ready(function() {
    
        step_slider = new StepSlider('selector');
    
        //for example, say that you have a div#next-button, you can then do this:
        $('#next-button').click(function(){
            step_slider.fire_onstep();
        });
    
    });//end domready
    
    
    })(jQuery);
    

    【讨论】:

    • 那不是一门课。
    • @low_rents:可能不适用于 ES6,但只要您可以从中实例化对象(新的 ClassName),它就是一个类。或者,它是一种(旧的)javascript 方式来执行类之类的操作,请记住,javascript 没有像 ActionScript 3 和 ES6 这样的真正的 oop/继承语法/糖。可能在 ES6 之前最好的 js oop 实现之一是 coffescript 创建 js 类的方式(只需创建一个并查看编译后的代码),但上面的实现是一个更简单的实现,它是一个很好的折衷方案,可以自包含、组织良好要实例化无限次的对象。
    猜你喜欢
    • 1970-01-01
    • 2022-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多