Event处理

今天抽时间写了一部分Event处理方面的函数愈发的觉得jQuery的优秀,自己前期的想法太粗糙,造成后面这些函数参数很多,操作很很不直观,看样子是要重构的节奏,还好小伙儿伴们安慰,架构都是改出来的。继续探索吧

浏览器兼容性

写Event处理的库函数一个难点就在于浏览器兼容性问题,在IE低版本浏览器中事件对象始终在window.event属性中,而在其它浏览器中event会作为事件处理程序中作为第一个参数传入。而且其Event对象的属性和方法也有诸多差异,在JavaScript与HTML交互——事件中基本有所总结,不过还是抄一段关于事件处理程序绑定方面的差异

1. 参数个数不相同,这个最直观,addEventListener有三个参数,attachEvent只有两个,attachEvent添加的事件处理程序只能发生在冒泡阶段,addEventListener第三个参数可以决定添加的事件处理程序是在捕获阶段还是冒泡阶段处理(我们一般为了浏览器兼容性都设置为冒泡阶段)

2. 第一个参数意义不同,addEventListener第一个参数是事件类型(比如click,load),而attachEvent第一个参数指明的是事件处理函数名称(onclick,onload)

3. 事件处理程序的作用域不相同,addEventListener得作用域是元素本身,this是指的触发元素,而attachEvent事件处理程序会在全局变量内运行,this是window,所以刚才例子才会返回undefined,而不是元素id

4. 为一个事件添加多个事件处理程序时,执行顺序不同,addEventListener添加会按照添加顺序执行,而attachEvent添加多个事件处理程序时顺序无规律(添加的方法少的时候大多是按添加顺序的反顺序执行的,但是添加的多了就无规律了),所以添加多个的时候,不依赖执行顺序的还好,若是依赖于函数执行顺序,最好自己处理,不要指望浏览器

最简单的四个

先写四个最简单的

  • getEvent:获取事件对象
  • getTarget:获取事件源对象
  • preventDefault:阻止事件默认行为
  • stopPropagation:阻止事件冒泡
(function (window) {
var ssLib = {
getEvent: function (e) {
return e ? e : window.event;
}, getTarget: function (e) {
var e = this.getEvent(e);
return e.target || e.srcElement;
}, preventDefault: function (e) {
var e = this.getEvent(e);
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
}, stopPropagation: function (e) {
var e = this.getEvent(e);
if (e.stopPropagation) {
e.stopPropagation();
} else {
e.cancelBubble = true;
}
}
};
window.ssLib = window.ss = ssLib;
})(window);

代码很简单,相信聪明的小伙儿伴们一看就懂,就不多做解释了

addEvent/removeEvent

  • addEvent:为元素绑定事件处理程序
  • removeEvent:移除元素事件处理程序
addEvent: function (element, type, handler, key) {
var key = key || handler;
if (element[type + key])
return false;
if (typeof element.addEventListener != "undefined") {
element[type + key] = handler;
element.addEventListener(type, handler, false);
}
else {
element['e' + type + key] = handler;
element[type + key] = function () {
element['e' + type + key](window.event);
};
element.attachEvent('on' + type, element[type + key]);
}
return true;
}, removeEvent: function (element, type, key) {
if (!element[type + key])
return false; if (typeof element.removeEventListener != "undefined") {
element.removeEventListener(type, element[type + key], false);
}
else {
element.detachEvent("on" + type, element[type + key]);
element['e' + type + key] = null;
} element[type + key] = null;
return true;
},

这两个函数兼容性写法有很多,结合了很多大牛的写法后我用的上面版本,这么些看似很复杂,实际上主要解决了上面提到的、除了多个事件处理程序执行顺序问题的浏览器兼容性问题,比较难看懂的IE绑定部分就是为了处理this而写的。

在使用的时候,可以显示传入一个key用于内部识别绑定函数,如果不绑定则使用handler本身作为key,所以可以这么用

ssLib.addEvent(element,'click',function(){},'test');
ssLib.removeEvent(element,'click','test'); function handler(){} ssLib.addEvent(element,'click',handler);
ssLib.removeEvent(element,'click',handler);

on/off

这个是看到jQuery的on/delegate和YUI 的delegate后萌发的想法,不过平时老用人家的没自己写过,仓促写了一个,感慨颇多,还是jQuery好使,这个版本目前有一定问题,明天优化一下

on: function (parent, type, handler,validater,key) {
var _key=key || handler;
parent['on'+type+_key]=function (e) {
var target = ssLib.getTarget(e);
var isFire = validater(target);
if (isFire) {
target[type + _key] = handler;
target[type + _key](e);
}
}; ssLib.addEvent(parent, type,parent['on'+type+_key] , key);
}, off: function (parent, type, key) {
if(typeof key=='function'){
ssLib.removeEvent(parent, type, parent['on'+type+key]);
}else{
ssLib.removeEvent(parent, type, key);
}
parent['on'+type+key]=null;
}

写法和刚才类似,不停的绕来绕去也是解决this问题,可以这么用

<div id="test">
<div id="t1">T1</div>
<div id="t2">T2</div>
</div>
var parent = document.getElementById('test');

        var handler=function () {
alert(this.id);
} var validater=function (obj) {
if(obj.parentNode.id=='test'){
return true;
}else{
return false;
}
} ss.on(parent, 'click', handler, validater); ss.off(parent,'click',handler); ss.on(parent, 'click', handler, validater,'delegate'); ss.off(parent,'click','delegate');

ready

用过jQuery的同学肯定知道这个函数,写自己库的时候是各种惊羡啊,于是乎加到了自己的库里

ready: function (fn) {
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", function () {
document.removeEventListener("DOMContentLoaded", arguments.callee, false);// 防止多次调用
fn();
}, false);
} else if (document.addEvent) {
var doc = window.document, done = false;
// only fire once
var init = function () {
if (!done) {
done = true;
fn();
}
};
// polling for no errors
(function () {
try {
// throws errors until after ondocumentready
doc.documentElement.doScroll('left');// 文档加载完成后此方法可用
} catch (e) {
setTimeout(arguments.callee, 50);
return;
}
// no errors, fire
init();
})();
// trying to always fire before onload
doc.onreadystatechange = function () {
if (doc.readyState == 'complete') {
doc.onreadystatechange = null;
init();
}
};
}
}

要想看懂上面代码最好看看An alternative for DOMContentLoaded on Internet Explorer

最后

今天太晚了要去睡觉了,明天会优化一下代码并解释一下ready函数

 
 
分类: JavaScript

Event处理的更多相关文章

  1. 如何利用ETW(Event Tracing for Windows)记录日志

    ETW是Event Tracing for Windows的简称,它是Windows提供的原生的事件跟踪日志系统.由于采用内核(Kernel)层面的缓冲和日志记录机制,所以ETW提供了一种非常高效的事 ...

  2. [.NET] C# 知识回顾 - Event 事件

    C# 知识回顾 - Event 事件 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6060297.html 序 昨天,通过<C# 知识回顾 - ...

  3. Atitit 解决Unhandled event loop exception错误的办法

    Atitit 解决Unhandled event loop exception错误的办法 查看workspace/.metadata/.log org.eclipse.swt.SWTError: No ...

  4. Java模拟Windows的Event

    场景 开发中遇到一个场景,业务操作会不定时的产生工作任务,这些工作任务需要放入到一个队列中,而另外会有一个线程一直检测这个队列,队列中有任务就从队列中取出并进行运算. 问题 业务场景倒是简单,只不过这 ...

  5. 事件EVENT与waitforsingleobject的使用

    事件event与waitforsingleobject的配合使用,能够解决很多同步问题,也可以在数据达到某个状态时启动另一个线程的执行,如报警. event的几个函数: 1.CreateEvent和O ...

  6. 火狐浏览器中event不起作用解决办法--记录(一)

    今天遇到了这个问题.IE,谷歌下都没问题,但在FF下却不起作用,很郁闷查了半天,看别人博文写了老长,结果试了要么起作用,但太麻烦,要么不起作用,说了那么多跟没说一样. 其实只要这一句代码就行:e=ar ...

  7. Event事件

    妙味课堂-Event事件 1.焦点:当一个元素有焦点的时候,那么他就可以接受用户的输入(不是所有元素都能接受焦点) 给元素设置焦点的方式: 1.点击 2.tab 3.js 2.(例子:输入框提示文字) ...

  8. Event Sourcing Pattern 事件源模式

    Use an append-only store to record the full series of events that describe actions taken on data in ...

  9. 严重: Exception sending context initialized event to listener instance of class

    问题描述:Exception sending context initialized event to listener instance of class org.springframework.w ...

  10. [转载]C#委托和事件(Delegate、Event、EventHandler、EventArgs)

    原文链接:http://blog.csdn.net/zwj7612356/article/details/8272520 14.1.委托 当要把方法作为实参传送给其他方法的形参时,形参需要使用委托.委 ...

随机推荐

  1. 前端学习笔记(zepto或jquery)——对li标签的相关操作(三)

    对li标签的相关操作——八种方式遍历li标签并获取其值 $("ul>li").forEach(function(item,index){ alert(index+" ...

  2. OpenVPN多处理之-最新架构

    好久没有更新这个系列了,由于我之前也说过,前段时间实在太忙了,并且早在一个月前就预示着本月将更加忙!事实也确实如此!最终在国庆前夕完毕了既定的计划,心里也最终能够长出一口气了.近期在忙什么呢?事实上就 ...

  3. 还是畅通project(杭州电1233)

    还是畅通project Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tota ...

  4. c# p2p 穿透(源码加密)

    http://blog.oraycn.com/ESFramework_Demo_P2P.aspx 测试,完全OK!  我很喜欢这个.可以源码是加密的!我希望实现 web 版本的p2p视频观看,aehy ...

  5. Bash shell 简单的并行任务,并等待

    首先启动两个command line对于实验 第一 command line 依次输入: bash$ sleep 10001 & [1] 38272 bash$ job1=$! bash$ s ...

  6. javascript通过数日两个日期之间的比较分离

    $(function () {  var starttime = transdate("2014-09-30 15:53:00");  var endtime = transdat ...

  7. DateTime.ToString("dd/MM/yyyy");后,不能直接Convert.ToDateTime的解决:

    原文:DateTime.ToString("dd/MM/yyyy");后,不能直接Convert.ToDateTime的解决: DateTime.ToString("dd ...

  8. libvlc media player in C# (part 2)

    原文 http://www.helyar.net/2009/libvlc-media-player-in-c-part-2/ I gave some simplified VLC media play ...

  9. npm err错误

    npm ERR!无法安装任何包的解决办法 通过config命令: npm config set registry http://registry.cnpmjs.org

  10. Serv-U执行CMD命令

    site exec + 命令.比如关机: site exec shutdown -r -t 0 注意,网上很多教程在前面加了一个“quote”,实测根本无效,不知道那些教材是怎么回事. 执行方式有很多 ...