当使用类似以下代码时,
$(function(){
$("#hr_three").click(function(event){
alert('阻止时间冒泡');
event.stopPropagation();
});
});
<form id="form1">
<div id="divOne" onclick="alert('我是最外层');">
<div id="divTwo" onclick="alert('我是中间层!')">
<a id="hr_three" onclick="alert('我是最里层!')">点击我</a>
</div>
</div>
</form>
jquery会将$("#hr_three")元素与click事件进行绑定,首先jquery会进行事件注册,如下代码:
// 对以下所有事件进行绑定
jQuery.each( ( "blur focus focusin focusout load resize scroll unload click dblclick " +
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
"change select submit keydown keypress keyup error contextmenu" ).split( " " ),
function( i, name ) {
// Handle event binding
// 将事件属性添加到jQuery对象
jQuery.fn[ name ] = function( data, fn ) {
// 根据调用参数数量进行不同调用,本例中调用this.on方法,也就是jQuery对象的on方法
return arguments.length > 0 ?
this.on( name, null, data, fn ) :
this.trigger( name );
};
} );
// 对jQuery.fn进行方法功能增强
jQuery.fn.extend( {
on: function( types, selector, data, fn ) {
// 调用全局on方法
return on( this, types, selector, data, fn );
}
...
}
function on( elem, types, selector, data, fn, one ) {
...
// elem参数指向jQuery对象,调用jQuery对象each方法
return elem.each( function() {
jQuery.event.add( this, types, fn, data, selector );
} );
}
jQuery.fn = jQuery.prototype = {
...
each: function( callback ) {
// each方法是由elem实例调用,因此this指向elem, 这里最终调用jQuery扩展的each方法,如下段代码
return jQuery.each( this, callback );
},
...
}
jQuery.extend( {
...
each: function( obj, callback ) {
var length, i = 0;
// 判断是否是类数组,有length属性并且带有length - 1属性则为类数组,在init方法增强this对象时,已将 //this对象设置了这两个属性,因此增强后的this对象为类数组
if ( isArrayLike( obj ) ) {
/**
obj为jQuery对象,此对象是init方法返回的this,this为针对不同元素增强后的jQuery对象,下面代码是在init方法中对jQuery对象进行了属性增强,增加了长度属性以及0属性,
if ( elem && elem.parentNode ) {
// Inject the element directly into the jQuery object
this.length = 1;
this[ 0 ] = elem;
}
this.context = document;
this.selector = selector;
return this;
*/
length = obj.length;
for ( ; i < length; i++ ) {
// 方法回调,更改回调方法上下文环境为obj[i],实际上obj[i]就是init方法的this对象的0属性, // this[ 0 ] = elem; elem对象就是html的dom元素
// elem = document.getElementById( match[ 2 ] ); 因此回调方法的上下文环境就为dom元素, // 本例中就是a元素,即document.getElementById("hr_three")
if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
break;
}
}
} else {
for ( i in obj ) {
if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
break;
}
}
}
return obj;
},
...
});
最终调用回调方法
// this为dom元素,types为click, fn为触发方法
jQuery.event.add( this, types, fn, data, selector );
在jQuery.event.add 方法中定义事件处理方法
if ( !( eventHandle = elemData.handle ) ) {
eventHandle = elemData.handle = function( e ) {
// Discard the second event of a jQuery.event.trigger() and
// when an event is called after a page has unloaded
return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
jQuery.event.dispatch.apply( elem, arguments ) : undefined;
};
}
...
// 生成处理对象
handleObj = jQuery.extend( {
type: type,
origType: origType,
data: data,
handler: handler,
guid: handler.guid,
selector: selector,
needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
namespace: namespaces.join( "." )
}, handleObjIn );
// 将处理对象存入到handlers数组
if ( selector ) {
handlers.splice( handlers.delegateCount++, 0, handleObj );
} else {
handlers.push( handleObj );
}
...
对elem增加click事件监听,elem为dom元素(本例中为id是hr_three的a元素)
if ( elem.addEventListener ) {
// eventHandle是本方法中定义的事件处理方法,见上段代码
elem.addEventListener( type, eventHandle );
}
至此,a元素已经绑定了click事件,当a元素产生点击事件时,会触发eventHandle指向的方法。
// eventHandle指向的方法参数e为pointerEvent对象
eventHandle = elemData.handle = function( e ) {
// Discard the second event of a jQuery.event.trigger() and
// when an event is called after a page has unloaded
return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
// elem为a元素,arguments为调用参数数组,元素0为参数e
// elem为jQuery.event.dispatch方法的上下文环境,arguments[0]为方法的唯一参数
jQuery.event.dispatch.apply( elem, arguments ) : undefined;
};
可以通过以下代码模拟元素增加监听效果,监听方法参数e就是pointerEvent对象:
var elem = document.getElementById("hr_three");
elem.addEventListener( "click", function(e) {
alert('阻止事件冒泡');
e.stopPropagation();
console.log(e);
} );
继续jQuery.event.dispatch方法
jQuery.event = {
...
// event参数为pointerEvent对象
dispatch: function( event ) {
// 将pointerEvent对象转换为jQuery.Event对象
// Make a writable jQuery.Event from the native event object
event = jQuery.event.fix( event );
// 取得处理对象数组
handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
args[ 0 ] = event;
// 将处理对象数组放入处理队列属性中
handlerQueue = jQuery.event.handlers.call( this, event, handlers );
while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
...
while ( ( handleObj = matched.handlers[ j++ ] ) &&
!event.isImmediatePropagationStopped() ) {
...
/**
调用处理方法,方法上下文为a元素,参数为jQuery.Event对象,处理方法event参数实际为args[0]指向的jQuery.Event对象,stopPropagation()方法为jQuery.Event实例方法,其中会将本实例的isPropagationStopped属性设置为true,因此再次外部while循环时,event.isPropagationStopped()即为true了。
function(event){
alert('阻止时间冒泡');
event.stopPropagation();
}
*/
ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
handleObj.handler ).apply( matched.elem, args );
...
}
...
}
},
...
}
到此,一个完整的jQuery事件绑定及触发调用的整个过程就完成了。
分享到:
相关推荐
《jQuery源码分析》 jQuery,作为一款广泛使用的JavaScript库,极大地简化了DOM操作、事件处理、动画制作以及Ajax交互。深入理解其源码对于提升JavaScript编程技能和优化前端性能至关重要。本文将从核心概念、设计...
### jQuery源码分析系列知识点概览 #### 一、总体架构与核心概念 - **前言开光**:介绍分析jQuery源码的目的和价值,强调通过深入研究源码,可以学习到先进的设计理念和实践技巧。 - **总体架构**:解析jQuery的...
总结,jQuery源码分析涉及的内容广泛,包括选择器引擎、事件处理、DOM操作、动画效果、Ajax通信以及插件开发等多个方面。深入理解jQuery源码,有助于我们更好地利用它来构建高效、易维护的Web应用。通过阅读中文注释...
深入理解jQuery源码有助于开发者更好地利用其API并优化性能。主要关注点包括: 1. **选择器引擎(Sizzle)**:jQuery 使用Sizzle作为其选择器引擎,它是如何快速高效地解析CSS选择器并找到匹配元素的。 2. **链式...
### jQuery源码分析 #### 一、概述 jQuery作为一个卓越的JavaScript库,以其简洁高效的特性在前端开发领域占据了一席之地。与Prototype、YUI、Mootools等其他JavaScript库相比,jQuery更加注重实用性,去除了一些...
### jQuery源码分析关键知识点详解 #### 一、前言 在深入了解jQuery源码之前,有必要先简要介绍一下jQuery的基本情况及其对JavaScript编程领域的重要意义。jQuery作为一个轻量级、功能丰富的JavaScript库,在Web...
jQuery源码分析系列涉及了对jQuery库内部实现的详细解读,jQuery作为前端开发中最常用的JavaScript库之一,它简化了DOM操作、事件处理、动画效果和AJAX交互等操作。通过深入分析jQuery的源码,开发者可以学习到先进...
这份中文注释的源码分析旨在帮助开发者逐步揭开jQuery的神秘面纱,提升JavaScript编程技能。 首先,jQuery的核心在于选择器引擎Sizzle。Sizzle是一个高效的选择器解析器,能够处理CSS1至CSS3的选择器,包括ID、类、...
### JQuery源码的奥秘逐行分析视频教程 #### JQuery简介 JQuery 是一款轻量级的 JavaScript 库,它极大地简化了 HTML 文档遍历、事件处理、动画以及 Ajax 交互等操作。JQuery 提供了一个简洁且强大的 API 接口,...
接着,源码分析揭示了 init 函数的实现逻辑。函数首先检查是否有 selector 参数传入,如果没有,那么就返回 this,即一个空的 jQuery 对象。如果 selector 是字符串,则根据字符串的类型和内容,进行不同处理。对于 ...
7. **源码结构分析**:jQuery源码采用模块化设计,分为核心、选择器、遍历、DOM操作等多个部分。理解其模块划分和依赖关系,有助于我们更好地理解代码结构和逻辑。 8. **学习资源**:除了这份源码解读,还有其他...
源码分析有助于理解网络请求的流程。 7. **插件开发**:jQuery的插件机制允许开发者扩展其功能。通过源码,我们可以学习如何构建自己的jQuery插件,以及如何利用`$.fn.extend()`方法。 在学习《Head First jQuery...
**jQuery 1.2.6 源码分析教程** jQuery 是一个广泛使用的 JavaScript 库,因其简洁的语法和强大的功能而备受开发者喜爱。在 jQuery 1.2.6 版本中,虽然它已经相对老旧,但其背后的实现原理和优化策略仍然值得深入...
**jQuery 源码分析与实例详解** jQuery 是一个广泛使用的 JavaScript 库,它极大地简化了 JavaScript 的 DOM 操作、事件处理、动画制作以及 AJAX 交互。本教程旨在通过源码解析、实例演示和详细注释,帮助新手快速...
【jQuery 源码分析最新1.2.6】 ...通过深入分析jQuery的源码,我们可以更好地理解其背后的实现原理,提升我们的JavaScript编程技巧。实际应用中,结合源码分析,可以更好地定制和优化jQuery的功能,以满足项目需求。
在jQuery 1.9.1中,事件系统是其核心功能之一,允许开发者方便地绑定、触发和管理事件。在本篇文章中,我们将深入探讨事件系统中的主动触发事件和模拟冒泡处理。首先,让我们来看一下`stopPropagation`函数。 `...
《jQuery 1.2.6 源码分析》 jQuery是JavaScript库的里程碑之作,它的出现极大地简化了网页的DOM操作,事件处理,动画设计和Ajax交互。本篇文章将聚焦于jQuery 1.2.6版本的源码,深入剖析其内部机制,帮助开发者更好...
综上所述,jQuery 1.2.6 的源码分析涵盖了选择器引擎的实现、DOM 操作、事件处理、动画效果、AJAX 请求、扩展性等多个方面,对于深入理解 JavaScript 库的构建和优化具有重要意义。通过深入学习,开发者不仅能提升...