jquery源码分析之jQuery事件绑定

当使用类似以下代码时,

$(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事件绑定及触发调用的整个过程就完成了。
潮汐研究作为海洋科学的关键分支,融合了物理海洋学、地理信息系统及水利工程等多领域知识。TMD2.05.zip是一套基于MATLAB环境开发的潮汐专用分析工具集,为科研人员与工程实践者提供系统化的潮汐建模与计算支持。该工具箱通过模块化设计实现了两大核心功能: 在交互界面设计方面,工具箱构建了图形化操作环境,有效降低了非专业用户的操作门槛。通过预设参数输入模块(涵盖地理坐标、时间序列、测站数据等),用户可自主配置模型运行条件。界面集成数据加载、参数调整、可视化呈现及流程控制等标准化组件,将复杂的数值运算过程转化为可交互的操作流程。 在潮汐预测模块中,工具箱整合了谐波分解法与潮流要素解析法等数学模型。这些算法能够解构潮汐观测数据,识别关键影响要素(包括K1、O1、M2等核心分潮),并生成不同时间尺度的潮汐预报。基于这些模型,研究者可精准推算特定海域的潮位变化周期与振幅特征,为海洋工程建设、港湾规划设计及海洋生态研究提供定量依据。 该工具集在实践中的应用方向包括: - **潮汐动力解析**:通过多站点观测数据比对,揭示区域主导潮汐成分的时空分布规律 - **数值模型构建**:基于历史观测序列建立潮汐动力学模型,实现潮汐现象的数字化重构与预测 - **工程影响量化**:在海岸开发项目中评估人工构筑物对自然潮汐节律的扰动效应 - **极端事件模拟**:建立风暴潮与天文潮耦合模型,提升海洋灾害预警的时空精度 工具箱以"TMD"为主程序包,内含完整的函数库与示例脚本。用户部署后可通过MATLAB平台调用相关模块,参照技术文档完成全流程操作。这套工具集将专业计算能力与人性化操作界面有机结合,形成了从数据输入到成果输出的完整研究链条,显著提升了潮汐研究的工程适用性与科研效率。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值