最近项目中有个大问题,就是前台的处理很大程度上用到了JS 来动态的更新页面,还融合了ajax技术。项目的内容其实并不多,但是有一个问题很纠结,就是一个搜索效果的浮动div问题。大概的效果就是点击查询事件,弹出一个搜索框,能够接受鼠标 键盘上下键的查询和确认添加到候选列表的处理。本来逻辑并不复杂,调用ajax从后台得到数据,在前台处理结果显示,选中隐藏就完全可以了。但是就是因为要处理的事件很多,导致了效果不佳,跟老大不断调试,以实用主义为主要,终于将效果调制想要的程度。今天看到一篇js事件机制的文章,把我的困惑全部一扫而空,我唯一的念想就是:记录记录!一定要记录下来!!!!
Javascript也是一门事件驱动的脚本语言,和其他桌面软件一样,WEB应用程序也有自己的事件驱动机制。比如:单击(onclick)、鼠标经过(onmouseover)、鼠标按下(onmousedown)等等。
在继续之前,我先详细讲讲Javascript的事件机制。 很久以前有个叫Netscape的姑娘,她制订了Javascript的一套事件驱动机制,事件产生的顺序如下所示:
事件流如箭头所指顺序开始由根节点往各节点派送,如果该节点上绑定有事件动作,则执行该动作,完毕后继续往下一节点走。
后来又有一个叫“IE”的小子,这孩子比较傲气,他认为“凭什么我要依照你的规则走”,于是他又创造了一套自己的规则:
------捕获-----> ------捕获-----> ------捕获-----> (捕获阶段)
document body div span
<-----外抛----- <-----外抛----- <-----外抛----- (冒泡阶段)
善良的Netscape以及其姐妹们都接受了媒婆的建议,采用了新的事件规则,而骄傲固执的IE小子始终按照自己的规则执行。最终使得这成为困扰前端开发人员的兼容性问题之一。
由于这两派浏览器的差异,其绑定的方法也不一样,其中,遵循标准的浏览器使用W3C定义的addEventListener函数绑定,函数定义如下:
function addEventListener(string eventFlag, function eventFunc, [bool useCapture=false])
eventFlag : 事件名称,如click、mouseover…
eventFunc: 绑定到事件中执行的动作
useCapture: 指定是否绑定在捕获阶段,true为是,false为否,默认为true
在事件监听流中可以使用event.stopPropagation()来阻止事件继续往下流
IE中使用自有的attachEvent函数绑定事件,函数定义如下:
function attachEvent(string eventFlag, function eventFunc)
eventFlag: 事件名称,但要加上on,如onclick、onmouseover…
eventFunc: 绑定到事件中执行的动作
在事件监听流中可以使用window.event.cancelBubble=false来阻止事件继续往下流
<script language="javascript"> //Javascript 事件演示 window.onload = function(){ var hideBox = function(event){ document.getElementById('status_show').style.display = 'none'; document.getElementById('status_hide').style.display = 'block'; }; var showBox = function(event){ document.getElementById('status_show').style.display = 'block'; document.getElementById('status_hide').style.display = 'none'; stopEvent(event); }; var stopEvent = function(event){ e = event || window.event; if(e.stopPropagation){ e.stopPropagation(); }else { e.cancelBubble = true; } }; if(document.addEventListener){ document.addEventListener('click', hideBox, false); document.getElementById('status_hide').addEventListener('click', showBox, false); document.getElementById('status_show').addEventListener('click', stopEvent, false); }else { //For IE document.attachEvent('onclick', hideBox); document.getElementById('status_hide').attachEvent('onclick', showBox); document.getElementById('status_show').attachEvent('onclick', stopEvent, showBox); } }; </script> 看完这个东西,我们的实现就差多了,我们为了避免事件处理,我们通过var 一个变量来控制是否执行事件的响应处理,这里是实现了功能,但是跨浏览器估计就差劲了。 对浏览器的支持性做必要的检查
if (Netscape) { use Netscape model } else if (Explorer) { use Microsoft model }
访问这个事件所以你可以读出他的属性,通常你的事件处理程序开始如下:
function doSomething(e) { if (!e) var e = window.event // e refers to the event }
读取他的属性
function doSomething(e) { if (!e) var e = window.event if (e.keyCode) code = e.keyCode;// for ie else if (e.which) code = e.which; // for netScape }
希望事件冒泡。如果不希望发生事件冒泡,那么就阻止他:
function doSomething(e) { if (!e) var e = window.event // handle event e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); }