`
zhouyrt
  • 浏览: 1173384 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

读jQuery之十三(触发事件核心方法)

 
阅读更多

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

在  事件模块的演变  我使用了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

 

一个事件的发生在某些元素中可能会导致两种动作,一个是默认行为,一个是事件handler。如链接A

<a href="http://mail.sina.com.cn" onclick="alert(1);">新浪邮箱</a>

 

点击后,弹出1(事件handler),点确定跳转(默认行为)到了mail.sina.com.cn。因此,设计的触发事件的函数要考虑到这两种情况。

 

 

jQuery使用.trigger和.triggerHandler区分了这两种情况:

.trigger  执行事件hanlder/执行冒泡/执行默认行为

.triggerHandler  执行事件handler/不冒泡/不执行默认行为

 

.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 );

 

 

有三种情况

1,event 本身就是jQuery.Event类的实例

2,event是个普通js对象(非jQuery.Event类的实例)

3,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() );

 

这段代码很重要,做了以下事情

1,取handle

2,执行

3,执行通过onXXX方式添加的事件(如onclick="fun()")

4,取父元素

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()使链接跳转。

 

 

 

  • 大小: 8.1 KB
分享到:
评论

相关推荐

    读jQuery之十四 (触发事件核心方法)

    文章接着介绍了jQuery内部实现的事件触发核心方法jQuery.event.trigger。该方法允许开发者触发一个指定类型的事件,并允许传递数据给事件处理函数。它还区分了是否执行默认行为和是否冒泡,这对于复杂的事件处理逻辑...

    读jQuery之十一 添加事件核心方法

    在探讨jQuery实现事件添加的核心方法时,我们首先要明确几个概念:elem、types、handler和data,这些是jQuery.event.add方法的主要参数。Elem指的是要添加事件监听的HTML元素,通常是HTMLElement类型。Types则是指定...

    读jQuery之十 事件模块概述

    在jQuery的事件模块中,`jQuery.event.add`是添加事件的核心方法。所有的`bind`、`one`、`live`等方法实际上都依赖于`jQuery.event.add`来完成事件的添加工作。这意味着,虽然表层API众多,但其底层的实现是统一和...

    详解jQuery中的事件

    本文将深入探讨jQuery中事件处理的核心概念、方法以及常见的应用场景。 首先,jQuery提供了一种更加优雅的方式来处理DOM加载完成的事件。在JavaScript中,我们通常使用`window.onload`来确保所有资源(包括图片)...

    jQuery的使用方法例子

    以上只是jQuery核心API的一部分,实际使用中还有更多的方法和功能,如AJAX的全局事件、插件机制等。通过熟练掌握这些基础API,开发者可以轻松实现网页的动态交互,提高开发效率。在实际项目中,配合详细的文档和示例...

    尚硅谷_教学课件_jQuery

    3. **强大的事件处理**:jQuery封装了JavaScript的事件处理,允许开发者用`.on()`、`.click()`等方法绑定事件,使事件处理更加便捷。 4. **丰富的动画效果**:jQuery的`.animate()`方法可以创建自定义动画,而`....

    jquery-3.5.1.rar

    此外,`.off()`可以用来移除已绑定的事件,`.trigger()`可以触发特定的事件。 动画效果是jQuery的一大亮点。`.fadeIn()`, `.slideUp()`, `.animate()`等方法使得创建平滑的过渡效果变得简单。例如,`$("#element")....

    jquery-1.6.4

    3. **事件处理**:jQuery简化了事件绑定和触发,如`$("button").click(function() { ... })`用于在按钮点击时执行指定的函数。 4. **动画效果**:内置的`.fadeIn()`, `.slideUp()`, `.animate()`等方法,让创建动态...

    jquery1.7_2离线版本API文档

    3. **事件处理**:jQuery简化了事件绑定和解绑的过程,如`click(fn)`用于添加点击事件,`bind(eventType,fn)`绑定多种事件,`off(eventType)`解除事件绑定,`trigger(eventType)`触发事件。 4. **动画效果**:...

    Jquery中文帮助文档

    3. **事件处理(Events)**:jQuery提供了一种统一的方式来绑定和触发事件。例如,`click()`、`mouseover()`、`mouseout()`等方法用于绑定事件,`$(document).ready()`确保在DOM加载完成后执行指定的代码。 4. **...

    jQuery个人介绍幻灯片

    3. **封装**: jQuery将复杂的JavaScript代码封装成简洁的方法,使得代码更易读、易写。 **二、jQuery主要功能** 1. **DOM操作**: jQuery提供了丰富的API用于创建、查找、修改和删除DOM元素,如`append()`、`prepend...

    jquery 多选项下拉框

    本篇文章将详细探讨 jQuery 实现多选项下拉框的核心概念、实现方法以及相关技术。 一、jQuery 概述 jQuery 是一个广泛使用的 JavaScript 库,它简化了 JavaScript 的DOM操作、事件处理、动画设计和Ajax交互。通过...

    基于jquery+canvas实现的拖动插件

    jQuery的核心特性可以使得网页动态化和交互变得简单。本项目以"基于jquery+canvas实现的拖动插件"为主题,利用jQuery与HTML5的Canvas API,创建了一个允许用户点击并拖动图形的功能。 Canvas是HTML5引入的一个强大...

    jquery-syntax-3.1.1.zip

    jQuery的核心功能包括选择器(用于选取HTML元素)、遍历(遍历DOM树)、事件处理(绑定和触发事件)以及动画(创建平滑的视觉效果)。 在这个插件中,"jquery-syntax-3.1.1" 可能包含了以下组件和功能: 1. **...

    JQuery文档

    2. **链式操作**: jQuery对象可以连续调用多个方法,这使得代码更加紧凑和易读。例如,`$("#element").hide().slideUp();`会先隐藏元素,然后执行滑动隐藏动画。 3. **DOM操作**: jQuery提供了丰富的API来操作DOM,...

    Head First Jquery(中文版)

    jQuery提供了一种简洁的方式来绑定和触发这些事件,使代码更易读和维护。 动画效果是jQuery的一大亮点,它提供了多种内置方法来创建平滑的过渡和效果,如fadeIn()、fadeOut()、slideToggle()等。这些方法可以用于...

    jquery.hotkeys插件键盘按键监听事件代码.zip

    它将按键事件转换为可读的字符串,然后与预先绑定的函数进行匹配,触发相应的处理函数。开发者只需要提供一个或多个键的组合,即可轻松实现键盘快捷键的绑定。 三、使用方法 1. 引入jQuery和jQuery.hotkeys插件:...

Global site tag (gtag.js) - Google Analytics