事件处理函数中的 return false 方法最初由 Netscape 制定,当时还没有事件监听注册方法,浏览器只支持为一个标记绑定一个事件处理函数,由此 Netscape 规定如果事件处理函数返回 false ,将就要阻止浏览器的默认事件行为继续执行,这个事实规范在所有浏览器中都被支持,它用于单一事件绑定函数中。
在现行 DOM-Events 规范中已定义了 preventDefault 标准方法来阻止浏览器默认行为,该方法用来在事件监听处理程序中阻止浏览器默认事件触发。而 return false 语句只针对事件绑定函授处理方式生效,在事件监听处理程序中将不会阻止浏览器默认事件触发。
关于浏览器默认行为我们通常可以理解为某此用户操作后浏览器可以自动执行的行为动作,这个行为可能会触发某些固有事件,从而使得事件处理程序可以被执行。比较常见的为:用户点击超链接后浏览器会自动下载目标页面,或者在可输入区域点击鼠标后浏览器自动将输入光标调整到可输入区域内。
关于取消事件的详细描述请参考 DOM-Level-2-Events 规范 1.2.4. Event cancelation
关于 preventDefault 方法的描述请参考 DOM-Level-2-Events 规范 1.4. Event interface
Click 事件发生时,会触发一系列相关的事件消息,他们的执行顺序为 MouseDown、MouseUp、Click,相关说明请参照 DOM-Level-2-Events 规范 1.6.2. Mouse event types 中的 Click 部分。
当用户通过鼠标操作触发 click 事件时,基本的事件触发流程为:MouseDown 事件 --> MouseUp 事件 --> Click 事件。若被点击的元素可以获得焦点,并且当前还没有获得焦点时,会在 MouseDown 事件之后默认触发 Focus 事件,再依次触发其后的 MouseUp 和 Click 事件。
如果浏览器将 Focus 作为默认行为处理,那么在MouseDown 事件处理函数内取消浏览器默认行为后,被点击的可以获得焦点的元素,需要阻止其后的 Focus 默认事件行为被触发,并且该元素不能获得焦点。
在 IE 浏览器中,在 MouseDown 事件的处理函数中,取消浏览器默认行为执行后,如果点击的是可获得焦点的元素 (如 INPUT) ,那么他依然会获得焦点并触发 Focus 事件。
而在非 IE 浏览器中,此情况下元素无法获得焦点,也不会触发 Focus 事件。
这个差异可能会导致某些具体操作性质的应用功能在非 IE 浏览器中执行异常。
IE |
---|
在具体分析此问题之前,需要理解与这个问题有关的两个知识点:
现在进入正题,分析以下代码:
<script> window.onload = function (){ function stopDefault(e){ e = e || window.event; (e.preventDefault) ?e.preventDefault() :e.returnValue = false; } function addEvent(el, type, fn){ (el.addEventListener) ? el.addEventListener(type, fn, false) :(function () { el.attachEvent("on" + type, function(e){ fn.call(el,e); }); })(); } function setEvents(elment){ addEvent(elment,"mousedown",function (e){ this.value+=' mousedown 事件被触发'; stopDefault(e); }); addEvent(elment,"focus",function (e){ this.value+=' focus 事件被触发'; }); addEvent(elment,"mouseup",function (e){ this.value+=' mouseup 事件被触发'; }); addEvent(elment,"click",function (e){ this.value+=' click 事件被触发'; }); } setEvents(document.getElementsByTagName("input")[2]); } </script> <ol> <li> <h2> 鼠标默认行为触发顺序 </h2> <input style="width:100%;" onmousedown="this.value+=' mousedown 事件被触发 ';" onfocus="this.value+=' focus 事件被触发 '" onclick="this.value+=' click 事件被触发 '" onmouseup="this.value+=' mouseUp 事件被触发 '"> <p>点击文本域后显示 click 事件相关联的各个事件触发顺序。</p> </li> <li> <h2> 使用 return false 语句阻止 MouseDown 后续默认行为触发 </h2> <input style="width:100%;" onmousedown="this.value+=' mousedown 事件被触发 ';return false;" onfocus="this.value+=' focus 事件被触发 '" onclick="this.value+=' click 事件被触发 '" onmouseup="this.value+=' mouseUp 事件被触发 '"> <p>点击文本域后没有继续执行 focuse 事件内程序,则说明成功阻止了默认行为。</p> </li> <li> <h2>使用 preventDefault 方法阻止 MouseDown 后续默认行为触发 </h2> <input style="width:100%;"> <p>点击文本域后没有继续执行 focuse 事件内程序,则说明成功阻止了默认行为。</p> </li> </ol>
上例中,首先验证鼠标点击 INPUT 元素后默认触发的事件执行顺序:
事件触发顺序 | 1 | 2 | 3 | 4 |
---|---|---|---|---|
所有浏览器 | MouseDown 事件 | Focus 事件 | MouseUp 事件 | Click 事件 |
在所有浏览器中均为 MouseDown --> Focus --> MouseUp --> Click ,这与规范描述一致。
确定了 MouseDown 事件之后将要触发的事件消息后,在 INPUT 元素 (该元素在所有浏览器中均可获得焦点) 的 MouseDown 事件内,分别使用单一事件绑定方法和事件监听方法取消浏览器默认行为。
各浏览器中执行效果如下:
IE | Firefox Safari Chrome Opera | |
---|---|---|
MouseDown | 触发 | 触发 |
Focus | 触发 | 未触发 |
MouseUp | 触发 | 触发 |
Click | 触发 | 触发 |
实验结果表明:
如果被点击元素可以获得焦点,并且需要在 Focus 事件处理函数内执行具体业务逻辑,那么:
操作系统版本: | Windows 7 Ultimate build 7600 |
---|---|
浏览器版本: |
IE6
IE7 IE8 Firefox 3.6.9 Chrome 7.0.503.0 dev Safari 5.0.1 Opera 10.61 |
测试页面: | mousedown_focus.html |
本文更新时间: | 2010-09-09 |
preventDefault returnValue Browser Befault Behavior mousedown mouseup click focus event