jQuery事件处理最全.docx
- 文档编号:28044939
- 上传时间:2023-07-07
- 格式:DOCX
- 页数:25
- 大小:27.03KB
jQuery事件处理最全.docx
《jQuery事件处理最全.docx》由会员分享,可在线阅读,更多相关《jQuery事件处理最全.docx(25页珍藏版)》请在冰豆网上搜索。
jQuery事件处理最全
jQuery事件处理
(一)
1、jQuery事件绑定的用法:
$("elem").on(events,[selector],[data],handler);
events:
事件名称,可以是自定义事件名称
selector:
选择器
data:
事件触发时传递给事件处理函数
handler:
事件处理函数
2、on方法源码分析
on:
function(types,selector,data,fn,/*INTERNAL*/one){
varorigFn,type;
//如果types是对象,则说明是传入了多个事件
if(typeoftypes==="object"){
//如果selector不是string,则说明用户没有传入selector
if(typeofselector!
=="string"){
//把selector赋值给data
data=data||selector;
//selector置为undefined
selector=undefined;
}
//遍历types对象中的每一个元素,并递归调用自身
for(typeintypes){
this.on(type,selector,data,types[type],one);
}
returnthis;
}
//如果data和fn都为null,说明用户只传了前两个参数
if(data==null&&fn==null){
//把selector(第二个参数)赋值给fn
fn=selector;
//data和selector置为undefined
data=selector=undefined;
//如果fn为null,说明用户传了三个参数
}elseif(fn==null){
//如果selector的类型是string,说明用户没传data
if(typeofselector==="string"){
//把data赋值给fn
fn=data;
//把data置为undefined
data=undefined;
}else{
//否则的话,说明用户没传selector,而是传了data,将data赋值给fn
fn=data;
//将selector赋值给data
data=selector;
//将selector置为undefined
selector=undefined;
}
}
//如果用户传入的事件处理函数是false值,则将事件处理函数赋值为jQuery内部的returnFalse函数
if(fn===false){
fn=returnFalse;
//如果用户没传回调函数,返回this,this是啥?
返回this干嘛?
}elseif(!
fn){
returnthis;
}
//如果one为1,内部用,暂时没看到用途
if(one===1){
origFn=fn;
fn=function(event){
//Canuseanemptyset,sinceeventcontainstheinfo
jQuery().off(event);
returnorigFn.apply(this,arguments);
};
//UsesameguidsocallercanremoveusingorigFn
fn.guid=origFn.guid||(origFn.guid=jQuery.guid++);
}
//遍历this对象,调用jQueryevent对象的add方法处理事件
returnthis.each(function(){
jQuery.event.add(this,types,fn,data,selector);
});
},
通过分析on方法的源码发现,on方法并没有处理事件相关的任何事情,只是对用户传入的参数进行调整,真正处理事件的是event对象
3、首先看看event对象的构造函数都做了什么
jQuery.Event=function(src,props){
//余老板的suggest组件中也用到了这种方法
//检测this是不是Event对象,如果不是,new一个Event对象出来,这样就避免了外部new对象
if(!
(thisinstanceofjQuery.Event)){
returnnewjQuery.Event(src,props);
}
//如果有src,并且src有type属性
if(src&&src.type){
//定义originalEvent属性并将src赋值给它
this.originalEvent=src;
//定义type属性,并将src.type赋值给它
this.type=src.type;
//定义isDefaultPrevented属性并通过判断事件被阻止冒泡为其赋值
this.isDefaultPrevented=(src.defaultPrevented||
src.getPreventDefault&&src.getPreventDefault())?
returnTrue:
returnFalse;
//否则,将src赋值给type
}else{
this.type=src;
}
//如果用户传入props,则扩展Event或者覆盖原有的属性
if(props){
jQuery.extend(this,props);
}
//创建一个时间戳?
?
this.timeStamp=src&&src.timeStamp||jQuery.now();
//给这个Event对象一个标记
this[jQuery.expando]=true;
};
看event对象的构造函数发现,构造函数做了一些初始化操作。
在看一下event对象封装的一些方法。
4、jQuery的event对象
jQuery的event对象提供了如下方法和属性:
{
add:
function(){},
remove:
function(){},
trigger:
function(){},
dispatch:
function(){},
handlers:
function(){},
fix:
function(){},
simulate:
function(){},
global:
{},
props:
{},
fixHooks:
{},
keyHooks:
{},
mouseHooks:
{},
special:
{}
}
首先看add方法:
add:
function(elem,types,handler,data,selector){
varhandleObjIn,eventHandle,tmp,
events,t,handleObj,
special,handlers,type,namespaces,origType,
elemData=data_priv.get(elem);
//涉及到jQuery的另外一个大的方面:
缓存机制。
或许我应该先看缓存机制的。
。
。
//不为text、comment节点绑定数据,直接返回
if(!
elemData){
return;
}
//如果handler是一个有handler属性或方法的对象,则进行一些转移赋值操作
if(handler.handler){
handleObjIn=handler;
handler=handleObjIn.handler;
selector=handleObjIn.selector;
}
//检查handler是否有一个唯一的id,方便之后查找和删除
if(!
handler.guid){
//如果没有就为其设定一个唯一id
handler.guid=jQuery.guid++;
}
//如果elemData中没有events对象,则为其定义events属性并赋值为空对象
if(!
(events=elemData.events)){
events=elemData.events={};
}
//如果elemData中没有handle对象
if(!
(eventHandle=elemData.handle)){
//为elemData定义一个handle方法(事件处理函数)
eventHandle=elemData.handle=function(e){
//有点迷糊。
。
。
returntypeofjQuery!
==core_strundefined&&(!
e||jQuery.event.triggered!
==e.type)?
jQuery.event.dispatch.apply(eventHandle.elem,arguments):
undefined;
};
//AddelemasapropertyofthehandlefntopreventamemoryleakwithIEnon-nativeevents
eventHandle.elem=elem;
}
//处理types中传入的是通过空格分割的多个事件的情况
types=(types||"").match(core_rnotwhite)||[""];
t=types.length;
while(t--){
tmp=rtypenamespace.exec(types[t])||[];
type=origType=tmp[1];
namespaces=(tmp[2]||"").split(".").sort();
if(!
type){
continue;
}
//事件是否会改变当前状态,如果是则使用特殊事件,看event的special属性。
。
。
special=jQuery.event.special[type]||{};
//根据是否有selector判断使用哪种特殊事件(看完特殊事件再过来看这个地方)
type=(selector?
special.delegateType:
special.bindType)||type;
//根据新的type获取新的special
special=jQuery.event.special[type]||{};
//组装用于特殊事件处理的对象
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);
//如果是第一次调用,初始化事件处理队列(将同一事件的处理函数放入数组中)
if(!
(handlers=events[type])){
handlers=events[type]=[];
handlers.delegateCount=0;
//如果获取特殊事件监听方法失败,则使用addEventListener添加事件(抛弃attachEvent了吗?
)
if(!
special.setup||special.setup.call(elem,data,namespaces,eventHandle)===false){
if(elem.addEventListener){
elem.addEventListener(type,eventHandle,false);
}
}
}
//使用special的add方法进行处理
if(special.add){
//添加事件
special.add.call(elem,handleObj);
//设置handleObj中的handler属性的id
if(!
handleObj.handler.guid){
handleObj.handler.guid=handler.guid;
}
}
//?
?
?
if(selector){
handlers.splice(handlers.delegateCount++,0,handleObj);
}else{
handlers.push(handleObj);
}
//现在还没看到是干啥用的。
jQuery.event.global[type]=true;
}
//将elem清空,等待回收,避免内存泄漏
elem=null;
},
事件处理
(二)
通过之前对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(){
vare=this.originalEvent;
this.isDefaultPrevented=returnTrue;
if(e&&e.preventDefault){
e.preventDefault();
}
},
stopPropagation:
function(){
vare=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]){
returnevent;
}
vari,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=newjQuery.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;
}
returnfixHook.filter?
fixHook.filter(event,originalEvent):
event;
},
jQuery事件处理(三)
继续了解jQuery对浏览器兼容的处理
1、keyHooks对键盘按键的封装
keyHooks:
{
//一些键盘相关的属性
props:
"charcharCodekeykeyCode".split(""),
//新的event对象和原生的event对象作为参数传入filter
filter:
function(event,original){
//如果event中没有which属性,新声明一个which属性并赋值
if(event.which==null){
//原生event中如果有charCode,就将它的charCode赋值给event的which属性,否则将它的keyCode赋值给which属性
event.which=
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- jQuery 事件 处理