• js和jquery中的触发事件


    改别人的坑,遇到jquery选择器和fireEvent混用,不认识fireEvent方法报错。

    js的方法不能使用jquery的选择器去调用。

    1.fireEvent (IE上的js方法 )

    我们来看看fireEvent跟onclick()触发事件是否相同。看下面的代码:

    <ul onclick='alert(event.srcElement.innerHTML);'> 
    <li id='id1'>i am one;</li> 
    <li id='id2'>i am two;</li> 
    <li id='id3'>i am three;</li> 
    </ul> 
    <button onclick='document.getElementById("id1").fireEvent("onclick")'>fireEvent !</button>

    点击button后,触发ul的onclick事件,说明fireEvent会引起冒泡,而且没有发生像onclick()提示“对象不支持此属性或方法”,说明即使不添加id1的onclick事件也可以冒泡。 
    由此可以看出,IE中的fireEvent方法类似模拟用户的鼠标点击行为,而不是单纯的onclick。

    触发事件:

    触发事件,或称模拟用户动作。比如点击,我们可以用代码去模拟用户点击,达到的效果与真实的鼠标点击是一样的。

    在 事件模块的演变 我使用了dispatchEvent(标准) 和fireEvent(IE)来主动触发事件。如下

    ... 
    dispatch = w3c ? 
    function(el, type){ 
    try{ 
    var evt = document.createEvent('Event'); 
    evt.initEvent(type,true,true); 
    el.dispatchEvent(evt); 
    }catch(e){alert(e)}; 
    } : 
    function(el, type){ 
    try{ 
    el.fireEvent('on'+type); 
    }catch(e){alert(e)} 
    }; 
    ... 

    jQuery则完全没有用到dispatchEvent/fireEvent方法。它采用的是另外一种机制。 
    jQuery触发事件的核心方法是jQuery.event.trigger。它提供给客户端程序员使用的触发事件方法有两个:.trigger/.triggerHandler 

    代码如下:


    .trigger/.triggerHandler的源码如下 
    trigger: function( type, data ) { 
    return this.each(function() { 
    jQuery.event.trigger( type, data, this ); 
    }); 
    }, 
    triggerHandler: function( type, data ) { 
    if ( this[0] ) { 
    return jQuery.event.trigger( type, data, this[0], true ); 

    }, 


    可以看出,两者都调用jQuery.event.trigger。调用时一个没有传true,一个传了。传了true的triggerHander就表示仅执行事件handler。 
    此外还需注意一点区别:.trigger是对jQuery对象集合的操作,而.triggerHandler仅操作jQuery对象的第一个元素。如下 

    复制代码代码如下:

    <p>p1</p> 
    <p>p1</p> 
    <p>p1</p> 
    <script> 
    $('p').click(function(){alert(1)}); 
    $('p').trigger('click'); // 弹3次,即三个p的click都触发了 
    $('p').triggerHandler('click'); // 仅弹1次,即只触发第一个p的click 
    </script> 


    好了,是时候贴出jQuery.event.trigger的代码了 

    复制代码代码如下:

    trigger: function( event, data, elem, onlyHandlers ) { 
    // Event object or event type 
    var type = event.type || event, 
    namespaces = [], 
    exclusive; 
    ...... 


    这就是jQuery.event.trigger的定义,省略了大部分。下面一一列举 

    复制代码代码如下:

    if ( type.indexOf("!") >= 0 ) { 
    // Exclusive events trigger only for the exact event (no namespaces) 
    type = type.slice(0, -1); 
    exclusive = true; 


    这一段是为了处理.trigger('click!')的情形,即触发非命名空间的事件。变量exclusive挂在事件对象上后在jQuery.event.handle内使用。举个例子 

    复制代码代码如下:

    function fn1() { 
    console.log(1) 

    function fn2() { 
    console.log(2) 

    $(document).bind('click.a', fn1); 
    $(document).bind('click', fn2); 
    $(document).trigger('click!'); // 2 


    为document添加了两个点击事件,一个是具有命名空间的"click.a",一个则没有"click"。使用trigger时参数click后加个叹号"!"。从输出结果为2可以看出不触发命名空间的事件。总结一下: 
    .trigger('click') 触发所有的点击事件 
    .trigger('click.a') 仅触发“click.a” 的点击事件 
    .trigger('click!') 触发非命名空间的点击事件 
    接着看 

    复制代码代码如下:

    if ( type.indexOf(".") >= 0 ) { 
    // Namespaced trigger; create a regexp to match event type in handle() 
    namespaces = type.split("."); 
    type = namespaces.shift(); 
    namespaces.sort(); 


    这段就很好理解了,就是对.trigger('click.a')的处理,即对具有命名空间事件的处理。 
    接着看 

    复制代码代码如下:

    if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { 
    // No jQuery handlers for this event type, and it can't have inline handlers 
    return; 


    对于一些特殊事件如"getData"或对于已经触发过的事件直接返回。 
    往下 

    复制代码代码如下:

    event = typeof event === "object" ? 
    // jQuery.Event object 
    event[ jQuery.expando ] ? event : 
    // Object literal 
    new jQuery.Event( type, event ) : 
    // Just the event type (string) 
    new jQuery.Event( type ); 


    有三种情况 
    ,event 本身就是jQuery.Event类的实例 
    ,event是个普通js对象(非jQuery.Event类的实例) 
    ,event是个字符串,如"click" 
    续 
    event.type = type; 
    event.exclusive = exclusive; 
    event.namespace = namespaces.join("."); 
    event.namespace_re = new RegExp("(^|\.)" + namespaces.join("\.(?:.*\.)?") + "(\.|$)"); 
    需要注意exclusive/namespace/namespace_re挂到了event上了,在jQuery.event.handle中可以用到(事件命名空间)。 
    往下是 

    复制代码代码如下:

    // triggerHandler() and global events don't bubble or run the default action 
    if ( onlyHandlers || !elem ) { 
    event.preventDefault(); 
    event.stopPropagation(); 


    onlyHandlers 只在 .triggerHandler用到了,即不触发元素的默认行为,且停止冒泡。 
    下面是 

    复制代码代码如下:

    // Handle a global trigger 
    if ( !elem ) { 
    // TODO: Stop taunting the data cache; remove global events and always attach to document 
    jQuery.each( jQuery.cache, function() { 
    // internalKey variable is just used to make it easier to find 
    // and potentially change this stuff later; currently it just 
    // points to jQuery.expando 
    var internalKey = jQuery.expando, 
    internalCache = this[ internalKey ]; 
    if ( internalCache && internalCache.events && internalCache.events[ type ] ) { 
    jQuery.event.trigger( event, data, internalCache.handle.elem ); 

    }); 
    return; 


    这里是个递归调用。如果没有传elem元素,那么从jQuery.cache里取。 
    接着是 

    复制代码代码如下:

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


    属性,文本节点直接返回。 
    下面是 

    复制代码代码如下:

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


    先将参数data放入数组,event对象放在数组的第一个位置。 
    接着是 

    复制代码代码如下:

    // Fire event on the current element, then bubble up the DOM tree 
    do { 
    var handle = jQuery._data( cur, "handle" ); 
    event.currentTarget = cur; 
    if ( handle ) { 
    handle.apply( cur, data ); 

    // Trigger an inline bound script 
    if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { 
    event.result = false; 
    event.preventDefault(); 

    // Bubble up to document, then to window 
    cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; 
    } while ( cur && !event.isPropagationStopped() ); 


    这段代码很重要,做了以下事情 
    ,取handle 
    ,执行 
    ,执行通过onXXX方式添加的事件(如onclick="fun()") 
    ,取父元素 
    while循环不断重复这四步以模拟事件冒泡。直到window对象。 
    接下是 

    复制代码代码如下:

    // If nobody prevented the default action, do it now 
    if ( !event.isDefaultPrevented() ) { 
    var old, 
    special = jQuery.event.special[ type ] || {}; 
    if ( (!special._default || special._default.call( elem.ownerDocument, event ) === 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. 
    // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. 
    try { 
    if ( ontype && elem[ type ] ) { 
    // Don't re-trigger an onFOO event when we call its FOO() method 
    old = elem[ ontype ]; 
    if ( old ) { 
    elem[ ontype ] = null; 

    jQuery.event.triggered = type; 
    elem[ type ](); 

    } catch ( ieError ) {} 
    if ( old ) { 
    elem[ ontype ] = old; 

    jQuery.event.triggered = undefined; 


    这一段是对于浏览器默认行为的触发。如form.submit(),button.click()等。 
    注意,由于Firefox中链接的安全性限制,jQuery对链接的默认行为都统一为不能触发。即不能通过.trigger()使链接跳转。 

    (我是搬运工)

  • 相关阅读:
    [C#]mouse_event模拟点击时坐标参数无效?!
    体验boost::spirit
    喜讯,公司换宽屏液晶显示器了
    [疑难杂症]扩展AxWebBrowser的问题???
    VS 2005 BUG: 新增JScript文件编码问题引起乱码?
    在JavaScript中实现命名空间
    [C#]实现序列号生成器
    基于Web的仿WF工作流设计器
    分享:基于UDP协议实现可靠的数据传输
    远程控制之屏幕截取 小结
  • 原文地址:https://www.cnblogs.com/weiwang/p/5473302.html
Copyright © 2020-2023  润新知