代码之家  ›  专栏  ›  技术社区  ›  Stephen Thomas

如何让jQuery触发本机自定义事件处理程序

  •  5
  • Stephen Thomas  · 技术社区  · 10 年前

    有人知道获取jQuery所需的魔法吗 .trigger() 触发由( 不是jQuery )本机JavaScript事件处理程序?

    test = document.querySelectorAll('.test')[0];
    test.addEventListener('click', function() {
        console.log('click')
    });
    test.addEventListener('custom', function(ev) {
        console.log('custom', ev.detail)
    });
    
    // Custom Native -> Native works as expected
    test.dispatchEvent(new CustomEvent('custom', {detail: 'detail'})); // -> "custom" "detail"
    
    // Standard jQuery -> Native works as expected
    $(test).trigger('click'); // -> "click"
    
    // Custom jQuery -> Native does not work
    $(test).trigger('custom'); // -> No log?
    $(test).trigger({type: 'custom'}); // -> No log?
    

    codepen.io live example

    已编辑以添加:

    关于我的用例的更多细节。我正在开发一个依赖于自定义事件但本身不使用jQuery的库。但是,我想让这个库方便那些有jQuery的应用程序。

    4 回复  |  直到 10 年前
        1
  •  3
  •   Stephen Thomas    10 年前

    嗯,在调试器中单步执行jQuery源代码之后,似乎有了一个解决方案。不优雅,但可行。诀窍是添加 onxxxx 属性设置为元素,其中 xxxx 是事件名称。在问题中添加的代码将是:

    test.oncustom = function(ev, data) {
        // ev is the jQuery Event object
        // data is data passed to jQuery `.trigger()`
    }
    

    请注意,例如,jQuery不会将自定义数据添加到, ev.detail ,就像标准活动一样。相反,它将自定义数据作为附加参数传递。

        2
  •  2
  •   lukbl    10 年前

    我的想法是创建一个插件,它将作为一个包装器 trigger jquery中的函数:

    (function($) {
      $.fn.extend({
        trigger: function(type, data) {
          return this.each(function() {
            if (typeof type == "string" && type.startsWith("test:")) {
              this.dispatchEvent(new window.CustomEvent(type, data));
            }else{
               jQuery.event.trigger(type, data, this)
             }
          });
        }
      });
    })(jQuery);
    

    代码稍作修改,来自: https://github.com/jquery/jquery/blob/master/src/event/trigger.js#L185

    假设您按如下方式添加处理程序:

    test.addEventListener('test:custom', function(ev) {
      console.log('test:custom', ev.detail)
    });
    

    您可以通过以下方式发送:

    $(test).trigger('test:custom', {  detail: 'jquery'});
    

    缺点是您需要在所有自定义事件前面加上某种名称空间。

    JSFiddle

        3
  •  0
  •   Rhys Bradbury    10 年前

    https://learn.jquery.com/events/introduction-to-custom-events/

    在网页末尾,请参见:

    下面是在这两种情况下使用自定义数据的.on()和.trigger()的用法示例:

    $( document ).on( "myCustomEvent", {
        foo: "bar"
    }, function( event, arg1, arg2 ) {
        console.log( event.data.foo ); // "bar"
        console.log( arg1 );           // "bim"
        console.log( arg2 );           // "baz"
    });
    
    $( document ).trigger( "myCustomEvent", [ "bim", "baz" ] );
    
        4
  •  0
  •   rtrukhin    10 年前

    这不是魔术。jQuery解决过程中的问题 元素[类型] 你的 测验 元素没有 风俗 处理程序,但具有本机 点击 处理程序。

    因此,您的脏补丁可能如下所示:

    **test.custom = function () {console.log('custom fixed')};**
    

    请查看以下jquery-1.7.2.js中的代码片段:

    // Call a native DOM method on the target with the same name name as the     event.
    // Can't use an .isFunction() check here because IE6/7 fails that test.
    // Don't do default actions on window, that's where global variables be (#6170)
    // IE<9 dies on focus/blur to hidden element (#1486)
    if (ontype && elem[type] && ((type !== "focus" && type !== "blur") ||   event.target.offsetWidth !== 0) && !jQuery.isWindow(elem)) {
    // Don't re-trigger an onFOO event when we call its FOO() method
    old = elem[ontype];
    
    if (old) {
        elem[ontype] = null;
    }
    
    // Prevent re-triggering of the same event, since we already bubbled it above
    jQuery.event.triggered = type;
    elem[type]();
    jQuery.event.triggered = undefined;
    
    if (old) {
        elem[ontype] = old;
    }
    

    }