Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/389.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在使用jQuery';非DOM对象中的s on/trigger支持?_Javascript_Jquery - Fatal编程技术网

Javascript 在使用jQuery';非DOM对象中的s on/trigger支持?

Javascript 在使用jQuery';非DOM对象中的s on/trigger支持?,javascript,jquery,Javascript,Jquery,下面的示例显示了在自定义JavaScript对象中提供事件处理的两种常见的现代方法。(我认为。)该示例基于通过AJAX在jQuery中加载数据的常见场景,其中传入了一个参数,该参数也需要在最终发布的已完成事件中提供 CustomClass.prototype.loadData(param1) { var thisObj = this; $.ajax({ url : this.reqUrl, context: this, // There are various

下面的示例显示了在自定义JavaScript对象中提供事件处理的两种常见的现代方法。(我认为。)该示例基于通过AJAX在jQuery中加载数据的常见场景,其中传入了一个参数,该参数也需要在最终发布的已完成事件中提供

CustomClass.prototype.loadData(param1) {

  var thisObj = this;
  $.ajax({
    url : this.reqUrl,
    context: this,

    // There are various ways to do this, including writing the handlers inline
    // or using $.proxy. Shouldn't be important for this question.
    success : function(dataResp, textStatus) {thisObj.onSuccess(dataResp,
                                                                textStatus,
                                                                param1)}
  });
};

// Manage listeners. Storing functions here, but
// could also use objects with predefined functions.
CustomClass.prototype.addListener(callbackFunc) {
  this.listeners.Add(callbackFunc);
}

CustomClass.prototype.onSuccess(dataResp, textStatus, param1) {

  //**OPTION 1**
  // Publish event via callbacks/listeners
  for(var i=0; i<this.listeners; i++)
    this.listeners[i](dataResp, param1);

  //**OPTION 2**
  // Publish event via trigger/on
  $(this).trigger('my-event-name', [dataResp, param1]);

};
上述任一选项的结果相同。使用jquery的on/trigger支持消除了管理侦听器的代码需求,但是:

  • 一种方法肯定比另一种好吗?
  • 在使用on/trigger时是否有任何重要的权衡,例如性能?
关于对DOM元素使用事件侦听器样式编程的好处,有很多问题/答案。关于在非DOM对象中提供事件处理的各种方法,还有许多问题/答案。然而,对于非DOM对象的首选方法和潜在的权衡,我找不到任何明确的信息,特别是在上面的示例这样的非平凡用例中

编辑
…当然,在发布之后,我看到这(非常)接近了。但是,它并不表示除了向自定义对象添加其他属性之外,是否还有其他分支。另外,我相信我的问题提供了一个更清晰的用例。

在回答我自己的问题时:

在编写不作为DOM交互的一部分生成或使用事件的自定义对象时,最好使用回调。jQuery的on/trigger事件处理的使用继承了大量额外的代码路径,因为它与jQuery更大的事件处理子系统相挂钩。其中一些逻辑用于处理浏览器差异。之所以使用其他代码,是因为它重用和/或复制了web浏览器中的事件处理功能,但在跨浏览器上下文中

相比之下,使用自定义回调处理非常简单。Jquery还提供了$.Callbacks函数,它可以节省一些编码,还可以选择包含更高级的回调功能

对这个问题更完整的回答将提供各种方法的时间分析。然而,仅jquery v1.9.1的来源就提供了强有力的轶事证据:

jQuery的触发器方法:

trigger: function( event, data, elem, onlyHandlers ) {
    var handle, ontype, cur,
        bubbleType, special, tmp, i,
        eventPath = [ elem || document ],
        type = core_hasOwn.call( event, "type" ) ? event.type : event,
        namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];

    cur = tmp = elem = elem || document;

    // Don't do events on text and comment nodes
    if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
        return;
    }

    // focus/blur morphs to focusin/out; ensure we're not firing them right now
    if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
        return;
    }

    if ( type.indexOf(".") >= 0 ) {
        // Namespaced trigger; create a regexp to match event type in handle()
        namespaces = type.split(".");
        type = namespaces.shift();
        namespaces.sort();
    }
    ontype = type.indexOf(":") < 0 && "on" + type;

    // Caller can pass in a jQuery.Event object, Object, or just an event type string
    event = event[ jQuery.expando ] ?
        event :
        new jQuery.Event( type, typeof event === "object" && event );

    event.isTrigger = true;
    event.namespace = namespaces.join(".");
    event.namespace_re = event.namespace ?
        new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
        null;

    // Clean up the event in case it is being reused
    event.result = undefined;
    if ( !event.target ) {
        event.target = elem;
    }

    // Clone any incoming data and prepend the event, creating the handler arg list
    data = data == null ?
        [ event ] :
        jQuery.makeArray( data, [ event ] );

    // Allow special events to draw outside the lines
    special = jQuery.event.special[ type ] || {};
    if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
        return;
    }

    // Determine event propagation path in advance, per W3C events spec (#9951)
    // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
    if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {

        bubbleType = special.delegateType || type;
        if ( !rfocusMorph.test( bubbleType + type ) ) {
            cur = cur.parentNode;
        }
        for ( ; cur; cur = cur.parentNode ) {
            eventPath.push( cur );
            tmp = cur;
        }

        // Only add window if we got to document (e.g., not plain obj or detached DOM)
        if ( tmp === (elem.ownerDocument || document) ) {
            eventPath.push( tmp.defaultView || tmp.parentWindow || window );
        }
    }

    // Fire handlers on the event path
    i = 0;
    while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {

        event.type = i > 1 ?
            bubbleType :
            special.bindType || type;

        // jQuery handler
        handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
        if ( handle ) {
            handle.apply( cur, data );
        }

        // Native handler
        handle = ontype && cur[ ontype ];
        if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
            event.preventDefault();
        }
    }
    event.type = type;

    // If nobody prevented the default action, do it now
    if ( !onlyHandlers && !event.isDefaultPrevented() ) {

        if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
            !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {

            // 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)
            if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {

                // Don't re-trigger an onFOO event when we call its FOO() method
                tmp = elem[ ontype ];

                if ( tmp ) {
                    elem[ ontype ] = null;
                }

                // Prevent re-triggering of the same event, since we already bubbled it above
                jQuery.event.triggered = type;
                try {
                    elem[ type ]();
                } catch ( e ) {
                    // IE<9 dies on focus/blur to hidden element (#1486,#12518)
                    // only reproducible on winXP IE8 native, not IE9 in IE8 mode
                }
                jQuery.event.triggered = undefined;

                if ( tmp ) {
                    elem[ ontype ] = tmp;
                }
            }
        }
    }

    return event.result;
}
触发器:函数(事件、数据、元素、仅限句柄){
变量句柄,ontype,cur,
气泡类型,特殊,tmp,i,
eventPath=[elem | | document],
type=core\u hasOwn.call(event,“type”)?event.type:event,
namespaces=core_hasOwn.call(事件,“名称空间”)?event.namespace.split(“.”):[];
cur=tmp=elem=elem | |文档;
//不在文本和注释节点上执行事件
if(elem.nodeType==3 | | elem.nodeType==8){
返回;
}
//聚焦/模糊变形为聚焦输入/输出;确保我们现在没有触发它们
if(rfocumorph.test(type+jQuery.event.triggered)){
返回;
}
if(type.indexOf(“.”>=0){
//命名空间触发器;创建一个regexp以匹配handle()中的事件类型
名称空间=type.split(“.”);
type=namespaces.shift();
名称空间;
}
ontype=type.indexOf(“:”)<0&&“on”+type;
//调用者可以传入jQuery.Event对象、对象或事件类型字符串
事件=事件[jQuery.expando]?
活动:
新的jQuery.Event(type,typeof Event==“object”&&Event);
event.isTrigger=true;
event.namespace=namespaces.join(“.”);
event.namespace\u re=event.namespace?
新的RegExp(“(^.\\)”+名称空间。join(“\\。(?:.\.\.\.\.\\)”)+“(\\.\$)”:
无效的
//清除事件以防重复使用
event.result=未定义;
如果(!event.target){
event.target=elem;
}
//克隆任何传入数据并在事件前添加前缀,从而创建处理程序arg列表
数据=数据==空?
[活动]:
makeArray(数据,[event]);
//允许特殊事件超出界限
special=jQuery.event.special[type]|{};
如果(!onlyhandler&&special.trigger&&special.trigger.apply(元素,数据)==false){
返回;
}
//根据W3C事件规范(#9951),提前确定事件传播路径
//跳转到文档,然后跳转到窗口;查看全局所有者文档变量(#9724)
如果(!onlyHandlers&&!special.nouble&&!jQuery.isWindow(elem)){
BubbletType=special.delegateType | | type;
if(!rfocusMorph.test(气泡类型+类型)){
cur=cur.parentNode;
}
对于(;cur;cur=cur.parentNode){
eventPath.push(cur);
tmp=cur;
}
//仅当我们得到文档时才添加窗口(例如,不是普通的obj或分离的DOM)
如果(tmp==(elem.ownerDocument | | document)){
推送(tmp.defaultView | | tmp.parentWindow | | window);
}
}
//在事件路径上激发处理程序
i=0;
而((cur=eventPath[i++])&&!event.isPropagationStopped(){
event.type=i>1?
气泡类型:
特殊.bindType | |类型;
//jQuery处理程序
handle=(jQuery._数据(cur,“事件”)|{}[event.type]&&jQuery._数据(cur,“handle”);
if(句柄){
处理。应用(当前、数据);
}
//本机处理程序
handle=ontype&&cur[ontype];
if(handle&&jQuery.acceptData(cur)&&handle.apply&&handle.apply(cur,data)==false){
event.preventDefault();
}
}
event.type=类型;
//如果没有人阻止默认操作,请立即执行
如果(!onlyHandler&&!event.isDefaultPrevented()){
if((!special._default | | special._default.apply)(elem.ownerDocument,data)==false)&&
!(type==“单击”&&jQuery.nodeName(elem,“a”)&&jQuery.acceptData(elem)){
trigger: function( event, data, elem, onlyHandlers ) {
    var handle, ontype, cur,
        bubbleType, special, tmp, i,
        eventPath = [ elem || document ],
        type = core_hasOwn.call( event, "type" ) ? event.type : event,
        namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];

    cur = tmp = elem = elem || document;

    // Don't do events on text and comment nodes
    if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
        return;
    }

    // focus/blur morphs to focusin/out; ensure we're not firing them right now
    if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
        return;
    }

    if ( type.indexOf(".") >= 0 ) {
        // Namespaced trigger; create a regexp to match event type in handle()
        namespaces = type.split(".");
        type = namespaces.shift();
        namespaces.sort();
    }
    ontype = type.indexOf(":") < 0 && "on" + type;

    // Caller can pass in a jQuery.Event object, Object, or just an event type string
    event = event[ jQuery.expando ] ?
        event :
        new jQuery.Event( type, typeof event === "object" && event );

    event.isTrigger = true;
    event.namespace = namespaces.join(".");
    event.namespace_re = event.namespace ?
        new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
        null;

    // Clean up the event in case it is being reused
    event.result = undefined;
    if ( !event.target ) {
        event.target = elem;
    }

    // Clone any incoming data and prepend the event, creating the handler arg list
    data = data == null ?
        [ event ] :
        jQuery.makeArray( data, [ event ] );

    // Allow special events to draw outside the lines
    special = jQuery.event.special[ type ] || {};
    if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
        return;
    }

    // Determine event propagation path in advance, per W3C events spec (#9951)
    // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
    if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {

        bubbleType = special.delegateType || type;
        if ( !rfocusMorph.test( bubbleType + type ) ) {
            cur = cur.parentNode;
        }
        for ( ; cur; cur = cur.parentNode ) {
            eventPath.push( cur );
            tmp = cur;
        }

        // Only add window if we got to document (e.g., not plain obj or detached DOM)
        if ( tmp === (elem.ownerDocument || document) ) {
            eventPath.push( tmp.defaultView || tmp.parentWindow || window );
        }
    }

    // Fire handlers on the event path
    i = 0;
    while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {

        event.type = i > 1 ?
            bubbleType :
            special.bindType || type;

        // jQuery handler
        handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
        if ( handle ) {
            handle.apply( cur, data );
        }

        // Native handler
        handle = ontype && cur[ ontype ];
        if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
            event.preventDefault();
        }
    }
    event.type = type;

    // If nobody prevented the default action, do it now
    if ( !onlyHandlers && !event.isDefaultPrevented() ) {

        if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
            !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {

            // 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)
            if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {

                // Don't re-trigger an onFOO event when we call its FOO() method
                tmp = elem[ ontype ];

                if ( tmp ) {
                    elem[ ontype ] = null;
                }

                // Prevent re-triggering of the same event, since we already bubbled it above
                jQuery.event.triggered = type;
                try {
                    elem[ type ]();
                } catch ( e ) {
                    // IE<9 dies on focus/blur to hidden element (#1486,#12518)
                    // only reproducible on winXP IE8 native, not IE9 in IE8 mode
                }
                jQuery.event.triggered = undefined;

                if ( tmp ) {
                    elem[ ontype ] = tmp;
                }
            }
        }
    }

    return event.result;
}