Javascript学习指南(第2版)笔记(三) 排错、调试、事件捕获
2010-05-29 09:25
686 查看
1、排错、调试
2、事件
3、Event对象
4、事件冒泡
5、事件句柄和 this
6、DOM Level 2事件模型
7、测验
1、排错、调试
Firebug是最常用的 Firefox开发工具,同时常用的 Web工具还有 Web Developer toolkit,该工具功能包括页面 HTML和 CSS代码的校验、可访问性检查、查看 CSS和 cookies、检查图像、查看 JavaScript修改后的页面源代码(包括动态源代码)。
2、事件
事件包括:用户界面事件(鼠标、键盘触发的)、逻辑事件(一个处理的结果)、和变化事件(修改文档的操作)。
注:HTML DOM Event 对象 http://www.w3school.com.cn/htmldom/dom_obj_event.asp[/i]
内联模式/内联注册模式:
以属性的形式为 HTML元素添加属性的方法。
<body onload="var 1=23; i*=3; alert(i);">
<body onload="calcNumber();">
传统模式/传统注册模式:
通过对象属性将一个函数指派为事件句柄。如果想禁用事件处理,那么可以将事件句柄的值赋为 null。
window.onload = calcNumber;
注:
在 DOM Level 0事件模型中,任何对象只允许指定一个事件句柄。如果你想针对某一特定对象的某个事件指定多个函数,则需要在事件句柄代码中列出他们:
内嵌模式:
<body onload="helloMsg(); helloTwice();">
传统模式:
function helloMsg() {
var helloString = "hello there";
alert(helloString);
helloTwice();
}
当要求浏览器停止执行事件行为,可以从事件句柄函数中返回 false值。
3、Event对象
Event对象是和所有事件相关的。它有一些用来提供事件相关信息的属性,如 Web页面中鼠标点击的位置。
IE将 Event视为 window对象的属性。当处理事件时,将通过程序访问 window对象,其所包含的数据也会相应的进行填充。
在基于 Netscape的浏览器(如 Firefox、Mozilla、Opera和 Safari)中,获取 Event对象的方法是不同的:他将作为函数的一部分传入。
处理这些浏览器差异的方法之一是检查传入函数的 Event对象是否已经实例化。如果是,那么将这个 Event对象赋给一个局部变量;否则,将假定 window.event为该事件,并将其赋给这个局部变量。
注:HTML DOM Event 对象 http://www.w3school.com.cn/htmldom/dom_obj_event.asp[/i]
注:
在 IE中,fromElement 对于 mouseover 和 mouseout 事件,fromElement 引用移出鼠标的元素。
而在 Mozilla/Firefox中,relatedTarget 返回与事件的目标节点相关的节点。
要解决浏览器差异,可以使用:
var oldElement = theEvent.fromElement ? theEvent.fromElement : theEvent.relatedTarget;
4、事件冒泡
如果你为多个嵌套的元素设置相同的事件句柄,会发生什么呢?他们将以什么样的顺序触发?如果你想使得一次只影响一个元素,那么如何保存触发事件句柄的事件呢?
要管理元素堆栈中的事件,其中一个方法就是众所周知的事件冒泡。在事件冒泡中,最内部的元素将首先触发该事件,然后堆栈内的下一个元素触发该事件,以此类推,直到最外面的元素。如果事件句柄被指定给所有元素,那么这些事件将依次被触发。
如果 div2在 div1内部,而 div1又在 document内部,三者都做了事件处理。当事件触发的时候,优先最里面的 div2元素,然后是 div1元素,最后是 document元素。
如果你有一个元素堆栈,并且只希望一个元素触发该事件句柄,那么你可以取消事件冒泡机制。如果在 IE中要取消一个事件冒泡,可以使用 IE中事件的 cancelBubble属性;对于 Mozilla而言,则应该使用事件的 stopPropagation方法。你可以先检查 stopPropagation方法是否存在,然后根据其结果确定使用哪种方法:
5、事件句柄和 this
this关键字表示的是当前调用的函数或者方法的所有者。对于一个全局变量而言,它表示的就是 window对象。对于一个对象的方法而言,它表示的就是该对象实例。而在一个事件句柄中,它表示的就是接收到该事件的元素。
6、DOM Level 2事件模型
对于堆栈内元素的事件处理,还有一种被称为事件捕捉(event capturing)或 cascade-down的事件处理机制。对于前面这个包含3个元素的示例而言,事件将从最外面的元素开始触发:window -> div1 -> div2。
老事件模型和新的 DOM Level 2事件模型之间,主要区别:
a.新事件模型并不依赖于特定的事件来处理属性;
b.你可以对任何一个对象的任何一种事件注册多个事件句柄函数。
新的事件句柄提供的3个方法:
addEventListener,添加一个事件监听器;
removeEventListener,删除一个事件监听器;
dispatchEvent,分发一个新的事件。
示例:
object.addEventListener('event', eventFunction, boolean);
如 click或 load之类的事件是其第一参数;第二个参数是指定的事件句柄函数;第三个参数用来指定事件是以 cascade-down或者冒泡模式处理的。当第三个参数为 false时这个事件监听器将以冒泡模式处理,否则将把这个事件监听器改成事件捕捉模型。
如果你想停止事件执行时,可以在函数中调用 stopPropagation方法:
function cascadeDown(evnt) {
...
evnt.stopPropagation();
}
如果要彻底删除一个事件监听器,可以使用 removeEventListener方法:
document.removeEventListener("click", cascadeDown, true);
在 IE中,与 addEventListener和 removeEventListener方法相似的是 attachEvent和 detachEvent,对应语法是:
object.attachEvent("eventhandler", function);
第一个参数是事件句柄,第二个是其函数。detachEvent语法类似。
跨浏览器解决方案:
注:HTML DOM Event 对象 http://www.w3school.com.cn/htmldom/dom_obj_event.asp[/i]
注:HTML DOM Event 对象 http://www.w3school.com.cn/htmldom/dom_obj_event.asp
[/i]
7、测验
Q1:使用 DOM Level 0方法为 document的 click事件指定一个事件句柄函数。
A1:document.onclick = clickMe;
Q2:使用 DOM Level 2事件处理机制为 document添加 click事件句柄。
A2:document.addEventListener("click", clickMe, false);
Q3:如果使事件处理机制能安全运行所有浏览器?
A3:
if (evtObject.addEventListener) evtObject.addEventListener("click", clickMe, false);
else if (evtObject.attachEvent) evtObject.attachEvent("onclick", clickMe);
else if (evtObject.onclick) evtObject.onclick=clickMe;
Q4:对于为 document对象指定的 onclick事件句柄,如何知道是在屏幕的什么位置执行了单击操作?
A4:
如果使用 DOM Level 0事件处理系统,那么将无法使用 window对象的 event对象,也不能将其作为参数传给函数。
对于 DOM Level 2事件处理模型而言,event对象将会传给事件句柄函数,你可以通过 event对象访问其 screenX和 screenY属性。
Q5:使用 DOM Level 2事件系统,如何阻止从其他元素中冒泡上来的事件。
A5:
IE所支持的方法和绝大多数浏览器所支持的方法有所不同,因此你需要分别支持 IE和其他浏览器。你可以检查 event对象是否支持 stopPropagation方法。如果支持,则调用它;否则就将 cancelBubble属性的值设置为 true。
Q7:捕获 document对象的 keydown事件
A7:
2、事件
3、Event对象
4、事件冒泡
5、事件句柄和 this
6、DOM Level 2事件模型
7、测验
1、排错、调试
Firebug是最常用的 Firefox开发工具,同时常用的 Web工具还有 Web Developer toolkit,该工具功能包括页面 HTML和 CSS代码的校验、可访问性检查、查看 CSS和 cookies、检查图像、查看 JavaScript修改后的页面源代码(包括动态源代码)。
2、事件
事件包括:用户界面事件(鼠标、键盘触发的)、逻辑事件(一个处理的结果)、和变化事件(修改文档的操作)。
事件句柄 (Event Handlers)
HTML 4.0 的新特性之一是能够使 HTML 事件触发浏览器中的行为,比如当用户点击某个 HTML 元素时启动一段 JavaScript。下面是一个属性列表,可将之插入 HTML 标签以定义事件的行为。属性 | 此事件发生在何时... | IE | F | O | W3C |
---|---|---|---|---|---|
onabort | 图像的加载被中断。 | 4 | 1 | 9 | Yes |
onblur | 元素失去焦点。 | 3 | 1 | 9 | Yes |
onchange | 域的内容被改变。 | 3 | 1 | 9 | Yes |
onclick | 当用户点击某个对象时调用的事件句柄。 | 3 | 1 | 9 | Yes |
ondblclick | 当用户双击某个对象时调用的事件句柄。 | 4 | 1 | 9 | Yes |
onerror | 在加载文档或图像时发生错误。 | 4 | 1 | 9 | Yes |
onfocus | 元素获得焦点。 | 3 | 1 | 9 | Yes |
onkeydown | 某个键盘按键被按下。 | 3 | 1 | No | Yes |
onkeypress | 某个键盘按键被按下并松开。 | 3 | 1 | 9 | Yes |
onkeyup | 某个键盘按键被松开。 | 3 | 1 | 9 | Yes |
onload | 一张页面或一幅图像完成加载。 | 3 | 1 | 9 | Yes |
onmousedown | 鼠标按钮被按下。 | 4 | 1 | 9 | Yes |
onmousemove | 鼠标被移动。 | 3 | 1 | 9 | Yes |
onmouseout | 鼠标从某元素移开。 | 4 | 1 | 9 | Yes |
onmouseover | 鼠标移到某元素之上。 | 3 | 1 | 9 | Yes |
onmouseup | 鼠标按键被松开。 | 4 | 1 | 9 | Yes |
onreset | 重置按钮被点击。 | 4 | 1 | 9 | Yes |
onresize | 窗口或框架被重新调整大小。 | 4 | 1 | 9 | Yes |
onselect | 文本被选中。 | 3 | 1 | 9 | Yes |
onsubmit | 确认按钮被点击。 | 3 | 1 | 9 | Yes |
onunload | 用户退出页面。 | 3 | 1 | 9 | Yes |
内联模式/内联注册模式:
以属性的形式为 HTML元素添加属性的方法。
<body onload="var 1=23; i*=3; alert(i);">
<body onload="calcNumber();">
传统模式/传统注册模式:
通过对象属性将一个函数指派为事件句柄。如果想禁用事件处理,那么可以将事件句柄的值赋为 null。
window.onload = calcNumber;
注:
在 DOM Level 0事件模型中,任何对象只允许指定一个事件句柄。如果你想针对某一特定对象的某个事件指定多个函数,则需要在事件句柄代码中列出他们:
内嵌模式:
<body onload="helloMsg(); helloTwice();">
传统模式:
function helloMsg() {
var helloString = "hello there";
alert(helloString);
helloTwice();
}
当要求浏览器停止执行事件行为,可以从事件句柄函数中返回 false值。
3、Event对象
Event对象是和所有事件相关的。它有一些用来提供事件相关信息的属性,如 Web页面中鼠标点击的位置。
IE将 Event视为 window对象的属性。当处理事件时,将通过程序访问 window对象,其所包含的数据也会相应的进行填充。
function mouseDown() { var locString = "X = " + window.event.screenX + " Y = " + window.event.screenY; alert(locString); } document.onmousedown = mouseDown;
在基于 Netscape的浏览器(如 Firefox、Mozilla、Opera和 Safari)中,获取 Event对象的方法是不同的:他将作为函数的一部分传入。
function mouseDown(theEvent) { var locString = "X = " + theEvent.screenX + " Y = " + theEvent.screenY; alert(locString); } document.onmousedown = mouseDown;
处理这些浏览器差异的方法之一是检查传入函数的 Event对象是否已经实例化。如果是,那么将这个 Event对象赋给一个局部变量;否则,将假定 window.event为该事件,并将其赋给这个局部变量。
function mouseDown(nsEvent) { var theEvent = nsEvent ? nsEvent : window.event; //判断 nsEvent对象是否已定义。定义则赋值,否则选择 window.event属性 var locString = "X = " + theEvent.screenX + " Y = " + theEvent.screenY; alert(locString); } document.onmousedown = mouseDown;
鼠标 / 键盘属性
属性 | 描述 | IE | F | O | W3C |
---|---|---|---|---|---|
altKey | 返回当事件被触发时,"ALT" 是否被按下。 | 6 | 1 | 9 | Yes |
button | 返回当事件被触发时,哪个鼠标按钮被点击。 | 6 | 1 | 9 | Yes |
clientX | 返回当事件被触发时,鼠标指针的水平坐标。 | 6 | 1 | 9 | Yes |
clientY | 返回当事件被触发时,鼠标指针的垂直坐标。 | 6 | 1 | 9 | Yes |
ctrlKey | 返回当事件被触发时,"CTRL" 键是否被按下。 | 6 | 1 | 9 | Yes |
metaKey | 返回当事件被触发时,"meta" 键是否被按下。 | No | 1 | 9 | Yes |
relatedTarget | 返回与事件的目标节点相关的节点。 | No | 1 | 9 | Yes |
screenX | 返回当某个事件被触发时,鼠标指针的水平坐标。 | 6 | 1 | 9 | Yes |
screenY | 返回当某个事件被触发时,鼠标指针的垂直坐标。 | 6 | 1 | 9 | Yes |
shiftKey | 返回当事件被触发时,"SHIFT" 键是否被按下。 | 6 | 1 | 9 | Yes |
注:
在 IE中,fromElement 对于 mouseover 和 mouseout 事件,fromElement 引用移出鼠标的元素。
而在 Mozilla/Firefox中,relatedTarget 返回与事件的目标节点相关的节点。
要解决浏览器差异,可以使用:
var oldElement = theEvent.fromElement ? theEvent.fromElement : theEvent.relatedTarget;
4、事件冒泡
如果你为多个嵌套的元素设置相同的事件句柄,会发生什么呢?他们将以什么样的顺序触发?如果你想使得一次只影响一个元素,那么如何保存触发事件句柄的事件呢?
要管理元素堆栈中的事件,其中一个方法就是众所周知的事件冒泡。在事件冒泡中,最内部的元素将首先触发该事件,然后堆栈内的下一个元素触发该事件,以此类推,直到最外面的元素。如果事件句柄被指定给所有元素,那么这些事件将依次被触发。
如果 div2在 div1内部,而 div1又在 document内部,三者都做了事件处理。当事件触发的时候,优先最里面的 div2元素,然后是 div1元素,最后是 document元素。
如果你有一个元素堆栈,并且只希望一个元素触发该事件句柄,那么你可以取消事件冒泡机制。如果在 IE中要取消一个事件冒泡,可以使用 IE中事件的 cancelBubble属性;对于 Mozilla而言,则应该使用事件的 stopPropagation方法。你可以先检查 stopPropagation方法是否存在,然后根据其结果确定使用哪种方法:
function stopEvent(evnt) { if (evnt.stopPropagation) evnt.stopPropagation; else evnt.cancelBubble = true; } //注:IE 7中调试出错,提示信息 "stopPropagation为空或不是对象"。
5、事件句柄和 this
this关键字表示的是当前调用的函数或者方法的所有者。对于一个全局变量而言,它表示的就是 window对象。对于一个对象的方法而言,它表示的就是该对象实例。而在一个事件句柄中,它表示的就是接收到该事件的元素。
document.getElementById("first").onmousedown = function() { alert(this); //在 Firefox中将输出 "[object HTMLDivElement]" alert("first element event"); }
6、DOM Level 2事件模型
对于堆栈内元素的事件处理,还有一种被称为事件捕捉(event capturing)或 cascade-down的事件处理机制。对于前面这个包含3个元素的示例而言,事件将从最外面的元素开始触发:window -> div1 -> div2。
老事件模型和新的 DOM Level 2事件模型之间,主要区别:
a.新事件模型并不依赖于特定的事件来处理属性;
b.你可以对任何一个对象的任何一种事件注册多个事件句柄函数。
新的事件句柄提供的3个方法:
addEventListener,添加一个事件监听器;
removeEventListener,删除一个事件监听器;
dispatchEvent,分发一个新的事件。
示例:
object.addEventListener('event', eventFunction, boolean);
如 click或 load之类的事件是其第一参数;第二个参数是指定的事件句柄函数;第三个参数用来指定事件是以 cascade-down或者冒泡模式处理的。当第三个参数为 false时这个事件监听器将以冒泡模式处理,否则将把这个事件监听器改成事件捕捉模型。
function cascadeDown(evnt) { alert("Capturing: " + this); } function bubbleUp(evnt) { alert("Bubbling: " + this); } window.onload = setup; function setup(evnt) { //事件捕捉 document.addEventListener("click", cascadeDown, true); document.forms[0].addEventListener("click", cascadeDown, true); document.forms[0].elements[0].addEventListener("click", cascadeDown, true); //事件冒泡 document.addEventListener("click", bubbleUp, false); document.forms[0].addEventListener("click", bubbleUp, false); document.forms[0].elements[0].addEventListener("click", bubbleUp, false); } /* 在 Firefox中,单击按钮将顺序生成6个对话框 Capturing: [object HTMLDocument] Capturing: [object HTMLFormElement] Capturing: [object HTMLInputElement] Bubbling: [object HTMLInputElement] Bubbling: [object HTMLFormElement] Bubbling: [object HTMLDocument] */
如果你想停止事件执行时,可以在函数中调用 stopPropagation方法:
function cascadeDown(evnt) {
...
evnt.stopPropagation();
}
如果要彻底删除一个事件监听器,可以使用 removeEventListener方法:
document.removeEventListener("click", cascadeDown, true);
在 IE中,与 addEventListener和 removeEventListener方法相似的是 attachEvent和 detachEvent,对应语法是:
object.attachEvent("eventhandler", function);
第一个参数是事件句柄,第二个是其函数。detachEvent语法类似。
跨浏览器解决方案:
window.onload = setup; window.onunload = cleanup; function setup(evnt) { var evtObject = document.getElementById("clickme"); //检查对象模型 if (evtObject.addEventListener) evtObject.addEventListener("click", clickMe, false); else if (evtObject.attachEvent) evtObject.attachEvent("onclick", clickMe); else if (evtObject.onclick) evtObject.onclick=clickMe; } /*清理 在 IE中,需要跟踪 window的 unload事件,然后调用 detachEvent方法清理,释放相应的内存 而 addEventListener方法使用的内存是无需清理的。 */ function cleanup() { var evtObject = document.getElementById("clickme"); if (evtObject.detachEvent) evtObject.detachEvent("onclick", clickMe); } function clickMe() { alert("clickMe"); }
IE 属性
除了上面的鼠标/事件属性,IE 浏览器还支持下面的属性:属性 | 描述 |
---|---|
cancelBubble | 如果事件句柄想阻止事件传播到包容对象,必须把该属性设为 true。 |
fromElement | 对于 mouseover 和 mouseout 事件,fromElement 引用移出鼠标的元素。 |
keyCode | 对于 keypress 事件,该属性声明了被敲击的键生成的 Unicode 字符码。对于 keydown 和 keyup 事件,它指定了被敲击的键的虚拟键盘码。虚拟键盘码可能和使用的键盘的布局相关。 |
offsetX,offsetY | 发生事件的地点在事件源元素的坐标系统中的 x 坐标和 y 坐标。 |
returnValue | 如果设置了该属性,它的值比事件句柄的返回值优先级高。把这个属性设置为 fasle,可以取消发生事件的源元素的默认动作。 |
srcElement | 对于生成事件的 Window 对象、Document 对象或 Element 对象的引用。 |
toElement | 对于 mouseover 和 mouseout 事件,该属性引用移入鼠标的元素。 |
x,y | 事件发生的位置的 x 坐标和 y 坐标,它们相对于用CSS动态定位的最内层包容元素。 |
标准 Event 属性
下面列出了 2 级 DOM 事件标准定义的属性。属性 | 描述 | IE | F | O | W3C |
---|---|---|---|---|---|
bubbles | 返回布尔值,指示事件是否是起泡事件类型。 | No | 1 | 9 | Yes |
cancelable | 返回布尔值,指示事件是否可拥可取消的默认动作。 | No | 1 | 9 | Yes |
currentTarget | 返回其事件监听器触发该事件的元素。 | No | 1 | 9 | Yes |
eventPhase | 返回事件传播的当前阶段。 | Yes | |||
target | 返回触发此事件的元素(事件的目标节点)。 | No | 1 | 9 | Yes |
timeStamp | 返回事件生成的日期和时间。 | No | 1 | 9 | Yes |
type | 返回当前 Event 对象表示的事件的名称。 | 6 | 1 | 9 | Yes |
[/i]
7、测验
Q1:使用 DOM Level 0方法为 document的 click事件指定一个事件句柄函数。
A1:document.onclick = clickMe;
Q2:使用 DOM Level 2事件处理机制为 document添加 click事件句柄。
A2:document.addEventListener("click", clickMe, false);
Q3:如果使事件处理机制能安全运行所有浏览器?
A3:
if (evtObject.addEventListener) evtObject.addEventListener("click", clickMe, false);
else if (evtObject.attachEvent) evtObject.attachEvent("onclick", clickMe);
else if (evtObject.onclick) evtObject.onclick=clickMe;
Q4:对于为 document对象指定的 onclick事件句柄,如何知道是在屏幕的什么位置执行了单击操作?
A4:
如果使用 DOM Level 0事件处理系统,那么将无法使用 window对象的 event对象,也不能将其作为参数传给函数。
对于 DOM Level 2事件处理模型而言,event对象将会传给事件句柄函数,你可以通过 event对象访问其 screenX和 screenY属性。
Q5:使用 DOM Level 2事件系统,如何阻止从其他元素中冒泡上来的事件。
A5:
IE所支持的方法和绝大多数浏览器所支持的方法有所不同,因此你需要分别支持 IE和其他浏览器。你可以检查 event对象是否支持 stopPropagation方法。如果支持,则调用它;否则就将 cancelBubble属性的值设置为 true。
Q7:捕获 document对象的 keydown事件
A7:
window.onload = function() { if (document.addEventListener) document.addEventListener("keydown", getKey, false); else if (document.attachEvent) document.attachEvent("onkeydown", getKey); else if (document.onkeydown) document.onkeydown=getKey; } function getKey(evnt) { var theEvent = evnt ? evnt : window.event; alert(theEvent.which); //Firefox 返回值,IE 7提示 undefined }
相关文章推荐
- Javascript学习指南(第2版)笔记(四) 表单、表单事件及校验
- SilverLight学习笔记--Silverligh之在Javascript中捕获和处理Silverlight控件事件
- Javascript学习指南(第2版)笔记(一) Script、数据类型和变量、操作符和语句
- JavaScript权威设计--事件冒泡,捕获,事件句柄,事件源,事件对象(简要学习笔记十八)
- JavaScript学习笔记之事件冒泡和事件捕获
- Javascript学习指南(第2版)笔记(六) DOM、Ajax及其数据
- 事件流之事件冒泡与事件捕获<JavaScript高级程序设计>学习笔记
- JavaScript高级程序设计笔记 事件冒泡和事件捕获
- JavaScript 学习笔记 之事件
- 【JS学习笔记】06 JavaScript HTML DOM 事件
- JavaScript学习指南笔记
- JavaScript学习笔记 3-if-then 和Link Events(链接事件)
- JavaScript测试与调试学习笔记
- JavaScript高级程序设计(第2版) 学习笔记:(一)js函数依赖性
- JavaScript 学习笔记 事件二
- JavaScript 学习笔记(十六) js事件
- JavaScript高级程序设计笔记 事件冒泡和事件捕获
- JavaScript高级程序设计(第2版) 学习笔记:(五)js获取窗口大小
- 1.javascript中的事件处理程序【学习笔记】
- JavaScript学习笔记之事件处理机制