事件处理(二)
通过之前对event.add方法的分析,发现jQuery在事件注册期间,将用户绑定的事件通过jQuery的缓存系统储存在了$.cache中,
jQuery对事件主要做的事情:
1、事件管理
a、事件注册时,通过add方法,将事件储存在$.cahce[ 唯一ID ][ $.expand ][ 'events' ]上,events内部是“事件类型”:“事件处理函数数组”形式的对象
b、事件触发时,通过trigger和handler从cache中查找并执行
c、事件销毁时,通过removie方法从cache中查找并删除
2、浏览器兼容的处理
a、差异:
firefox、chrome、oprea、safari、IE9+都支持随事件传入事件处理函数
IE8-则只能从window对象获取
event对象内部封装的属性命名有差异,例如keycode、which
b、统一接口依赖event.fix方法,同时也依赖props、fixHooks、keyHooks、mouseHooks等event的属性
props中存储原生event对象的通用属性(所有浏览器都相同个)
keyHook.props 存储键盘事件的特有属性
mouseHooks.props 存储鼠标事件的特有属性
// 统一接口(jQuery中用到的event对象是对原event对象的扩展)
jQuery.Event.prototype = {
isDefaultPrevented: returnFalse,
isPropagationStopped: returnFalse,
isImmediatePropagationStopped: returnFalse,
preventDefault: function() {
var e = this.originalEvent;
this.isDefaultPrevented = returnTrue;
if ( e && e.preventDefault ) {
e.preventDefault();
}
},
stopPropagation: function() {
var e = this.originalEvent;
this.isPropagationStopped = returnTrue;
if ( e && e.stopPropagation ) {
e.stopPropagation();
}
},
stopImmediatePropagation: function() {
this.isImmediatePropagationStopped = returnTrue;
this.stopPropagation();
}
};
// 除了上面增加的一些方法,还对其它属性进行了修正
fix: function( event ) {
// 如果该event上存在jQuery.expando属性,说明已经是封装过的对象,直接返回该对象
if ( event[ jQuery.expando ] ) {
return event;
}
var i, prop, copy,
type = event.type,
// 将event赋值给originalEvent变量
originalEvent = event,
// 到fixHooks中看看有没有对应事件类型的修正
fixHook = this.fixHooks[ type ];
// 如果没有,则从mouseHooks或者是keyhooks中取,如果都没有就设置为空对象
if ( !fixHook ) {
this.fixHooks[ type ] = fixHook =
rmouseEvent.test( type ) ? this.mouseHooks :
rkeyEvent.test( type ) ? this.keyHooks :
{};
}
// 如果有修正后的属性,则和通用的属性连接起来并赋值给copy,否则直接将通用的属性赋值给copy
copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
// 创建一个jQuery的event对象
event = new jQuery.Event( originalEvent );
i = copy.length;
// 遍历copy,替换掉原生的一些属性。
while ( i-- ) {
prop = copy[ i ];
event[ prop ] = originalEvent[ prop ];
}
// event为什么会没有target
if ( !event.target ) {
event.target = document;
}
// 呃。。。
if ( event.target.nodeType === 3 ) {
event.target = event.target.parentNode;
}
return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
},