事件处理概述
客户端JavaScript程序(浏览器)采用了异步事件驱动编程模型(我的理解是交互驱动)。当文档、 浏览器、元素或与之相关的对象发生某些有趣的事情时,Web浏览器就会产生事件(event)。如果JavaScript应用程序关注特定类型的事件,那么它可以注册当这类事件发生时要调用的一个或多个函数。这种风格并非Web编程独有,所有使用图形用户界面的应用程序都采用了它。
一些重要的定义:
1⃣️ 事件类型(event type):是一个用来说明发生什么类型事件的字符串。例如,“mouse-move”表示用户移动鼠标,“keydown”表示键盘上某个键被按下。事件类型只是一个字符串,有时候又称之为事件名字(event name);

当一个事件发生时,它会先从浏览器顶级对象Window一路向下传递,一直传递到触发这个事件的那个元素,这也就是事件捕获(event capturing)过程。然而,一切并没有结束,事件又从这个元素一路向上传递到Window对象,这也就是事件冒泡(event bubble)过程(但是在IE8以及其之前版本中,事件模型并未定义捕获过程,只有冒泡过程)。
事件的分类
传统事件类型
- mousemove事件:用户每次移动或拖动鼠标时触发 (发生很频繁)。
JavaScript中常用的事件类型
1⃣️ UI事件
- load:当页面加载后在window上面触发,当所有框架加载完成后在框架上触发,当图像加载完成后在<img>元素上面触发。
- unload:当页面卸载后在window上面触发。
- abort:当用户停止下载过程时,如果嵌入的内容没有加载完,则在<object>元素上触发。
- error:当发生JavaScript错误时在window上面触发。
- select:当用户选择文本框(input或textarea)或一个字符串时触发。
- resize:当窗口或框架大小变化时在window上面触发。
- scroll:当用户滚动滚动条的元素中的内容时,在元素上触发。
EventUtil.addHandler(window, "load", function (event) {
alert("load");
}); //load事件
<body load="alert('load');">
<!-- Html代码 -->
</body>
建议尽可能使用JavaScript代码来定义load事件。
unload事件
EventUtil.addHandler(window, "resize", function (event) {
alert("resize");
}); /resize事件
2⃣️ 焦点事件
- focus,在得到焦点的元素上触发,这个事件不会冒泡。
- focusIn,在得到焦点的元素上触发 ,这个事件会冒泡。
- DOMFocusIn,在得到焦点的元素上触发,这个事件会冒泡。
- DOMFocusOut,在失去焦点的元素上触发。
- blur,在失去焦点的元素上触发,这个事件不会冒泡。
- focusout,在失去焦点的元素上触发,这个事件会冒泡。
let input1 = document.getElementById("input1");
input1.onfocus = function (event) {
alert("hi"); //hi
};
let input1 = document.getElementById("input1");
input1.onblur = function (event) {
alert("失去焦点"); //失去焦点
};
3⃣️ 鼠标与滚轮事件
- click:鼠标单击事件,当单击鼠标(一般为左键)或按下回车键时,会触发事件。
- dbclick:鼠标双击事件,当双击鼠标时,会触发事件。
- mousedown:当任意按下鼠标键时,会触发事件。
- mouseup:当释放鼠标铵键时,会触发事件。
- mouseover:当鼠标移动进到当前元素的区域就会触发事件。
- mouseout:当鼠标移出当前元素的区域就会触发事件。
- mousemove:当鼠标在当前元素区域内不断移动时,会重复触发事件。
let input1 = document.getElementById("input1");
input1.onmousedown = function (event) {
alert("按下鼠标按键");
};
当释放鼠标按键时:
let input1 = document.getElementById("input1");
input1.onmouseup = function (event) {
alert("释放鼠标按键");
};
当单击鼠标按键时:
let input1 = document.getElementById("input1");
input1.onclick = function (event) {
alert("点击鼠标按键");
};
当双击鼠标按键时:
let input1 = document.getElementById("input1");
input1.ondbclick = function (event) {
alert("双击鼠标按键");
};
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript</title>
</head>
<body>
<input id="input1" type="button" value="单击事件">
<script>
let input1 = document.getElementById("input1");
//客户区坐标,不包括页面滚动的距离
input1.onclick = function (event) {
alert("clientX:" + event.clientX + " clientY:" + event.clientY);
};
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript</title>
</head>
<body>
<input id="input1" type="button" value="单击事件">
<script>
let input1 = document.getElementById("input1");
//页面坐标位置,包括了页面滚动的距离
input1.onclick = function (event) {
alert("pageX:" + event.pageX + " pageY:" + event.pageY);
};
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript</title>
</head>
<body>
<input type="button"><br>
<input type="button"><br>
<input type="button"><br>
<input type="button"><br>
<input id="input1" type="button" value="单击事件">
<script>
let input1 = document.getElementById("input1");
//屏幕坐标
input1.onclick = function (event) {
alert("screenX:" + event.screenX + " screenY:" + event.screenY);
};
</script>
</body>
</html>
即使鼠标在同一点击事件,clientY与screenY的值是不同的,screenY的值大一些,这是因为浏览器的菜单栏与工具栏要占一定的空间。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript</title>
</head>
<body>
<input id="input1" type="button" value="单击事件">
<script>
let input1 = document.getElementById("input1");
input1.onclick = function (event) {
alert("修改键");
//定义一个Array类,用于保存用户触发了的修改键。
let keys = new Array();
//判断在按下鼠标键的同时,是否也按下了其它的修改键,如果按下了,
//将相应修改键的名称推入数组。
if (event.shiftKey) {
keys.push("shifKey");
}
if (event.ctrlKey) {
keys.push("ctrl");
}
if (event.altKey) {
keys.push("altKey");
}
//最后将数组中的值用join()方法以字符串的形式用逗号隔开。
alert("keys:" + keys.join(","));
};
</script>
</body>
</html>
注:鼠标默认的按键是最左边的为主按键,中间的滑轮为中间按键,最右边的为次按键,当然,用户可以自定义设置这三个按键。
<!doctype html>
<html lang="zh">
<head>
<meta charset="utf-8">
<title>JavaScript</title>
</head>
<body>
<input id="input1" type="button" value="单击事件">
<script>
let input1 = document.getElementById("input1");
input1.onmousedown = function (event) {
console.log("button属性");
//定义一个Array类,用于保存用户触发了的修改键。
let keys = new Array();
//判断在按下鼠标键的同时,是否也按下了其它的修改键,
//如果按下了,将相应修改键的名称推入数组。
if (event.shiftKey) {
keys.push("shif");
}
if (event.ctrlKey) {
keys.push("ctrl");
}
if (event.altKey) {
keys.push("alt");
}
//最后将数组中的值用join()方法以字符串的形式用逗号隔开。
console.log("keys:" + keys.join(","));
switch (event.button) {
case 0:
alert("用户按下鼠标的主按键");
break;
case 1:
alert("用户按下鼠标的中间按键");
break;
case 2:
alert("用户按下鼠标的次按键");
break;
}
};
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript</title>
</head>
<body>
<input id="inpt1" type="button" value="单击事件">
<script>
let inpt1 = document.getElementById("inpt1");
//鼠标单击事件,datail记录单击的次数。
inpt1.onclick = function (e) {
console.log(e.detail);
};
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript</title>
</head>
<body>
<input id="input1" type="button" value="单击事件">
<script>
let input1 = document.getElementById("input1");
//当触发mousewheel事件时,wheelDelta属性记录了滑动数据
document.onmousewheel = function (event) {
if (event.wheelDelta > 0) {
console.log("鼠标向前滑动");
} else if (event.wheelDelta < 0) {
console.log("鼠标身后滑动");
} else {
console.log("未滑动");
}
console.log(event.wheelDelta);
};
</script>
</body>
</html>
4⃣️ 键盘与文本事件
- keydown:按下键盘上的任意按键会触发事件,如果按住按键不放,则会重复触发事件。
- keyup:当释放键盘按键时会触发事件。
- keypress:当用户按住键盘上的字符键时会触发事件,如果按住不放,则会重复触发事件。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript</title>
</head>
<body>
<input id="input1" type="button" value="单击事件">
<script>
let input1 = document.getElementById("input1");
//当按下键盘按键时会触发。
document.onkeydown = function (event) {
console.log("您按下了按键");
};
//当按下的是字符键时会触发
document.onkeypress = function (event) {
console.log("您按下的是字符键");
};
//释放按键时会触发
document.onkeyup = function (event) {
console.log("您释放了按键");
};
</script>
</body>
</html>
键码
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript</title>
</head>
<body>
<input id="input1" type="button" value="单击事件">
<script>
let input1 = document.getElementById("input1");
document.onkeydown = function (event) {
console.log(event.keyCode);
};
document.onkeyup = function (event) {
console.log(event.keyCode);
};
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript</title>
</head>
<body>
<input id="input1" type="button" value="单击事件">
<script>
let input1 = document.getElementById("input1");
//keypress事件的event对象的charCode属性
document.onkeypress = function (event) {
console.log(event.charCode);
};
</script>
</body>
</html>
- textInput事件只有在可输入区域才能触发,而keypress事件就是只要任何获取焦点的元素就会触发该事件。
- 只有输入实际的字符才能触发textInput事件,而keypress事件,只要按下是否能影响文本显示的按键时就能触发。
<body>
<input id="text1" type="text" >
<script>
let text1 = document.querySelector("#text1");
text1.ontextInput = function (e) {
alert(e.date);
};
</script>
</body>
Version:0.9 StartHTML:0000000105 EndHTML:0000031901 StartFragment:0000000141 EndFragment:0000031861
5⃣️ 复合事件
6⃣️ 变动事件
- DOMSubtreeModified:在DOM结构中发生任何变化时触发。这个事件在其它事件触发后都会触发。
- DOMNodeRemoved:在节点从其父节点中移出时触发。(删除节点时)
- DOMNodeInserted:在一个节点作为另一个节点的子节点插入时触发。(插入节点)
- DOMNodeInsertedIntoDocument:在一个节点直接被插入到文档中或通过DOM子树结构插入到文档中时触发。
- DOMNodeRemovedFromDocument:在一个节点直接从文档中移出或通过DOM子树结构移出时触发。
<!doctype html>
<html lang="zh-en">
<head>
<meta charset="utf-8">
<title>变动事件之删除节点操作</title>
<style></style>
</head>
<body>
<ul id="myList">
<li>li 1</li>
<li>li 2</li>
<li>li 3</li>
<li>li 4</li>
</ul>
<script>
window.onload = function (e) {
//通过ID获取ul元素的引用
let list = document.querySelector("#myList");
/*首先是触发DOMNodeRemoved事件,event.relateNode包含对其父
节点的引用(即document.body),由document添加该事件处理程序也可以。*/
list.addEventListener("DOMNodeRemoved", function (e) {
console.log(e.type); //DOMNodeRemoved
console.log(e.target); // <ul>...</ul>
console.log(e.relateNode); //undefined
console.log(list.parentNode); //<body>...</body>
});
//接着在被删除节点上触发DOMNodeRemovedFromDocument事件
list.addEventListener("DOMNodeRemovedFromDocument",
function(e) {
console.log(e.type); //DOMNodeRemovedFromDocument
console.log(e.target); //<ul>...</ul>
});
//再接着在被删除节点的子节点上触发
DOMNodeRemovedFromDocument事件
list.firstChild.addEventListener("DOMNodeRemovedFromDocument",
function (e){
console.log(e.type); //DOMNodeRemoveFromDocument
console.log(e.target); //#text 因为<li>包含的是文本内容
});
/*随之触发DOMSubtreeModifined事件,该事件的目标是被删除节点的
父节点(即document.body)此时Event对象不会包含任何有关事件的信息,
所以以下的内容不会返回。*/
list.addEventListener("DOMSubtreeModified", function (e) {
console.log(e.type);
console.log(e.target);
});
//设置以上事件处理程序之后,该元素从其父节点中被删除。
list.parentNode.removeChild(list);
/*该方式也行,因为在这个例子中,<ul>元素的父节点就是<body>
document.body.removeChild(list);*/
}
</script>
</body>
</html>
- 首先在<ul>元素上触发DOMNodeRemoved事件,该事件的目标就是当前元素节点即<ul>,该事件的Event对象的relatedNode引用的是其父节点即document.body。
- 接着,在<ul>元素上触发DOMNodeRemovedFromDocument事件,该事件的目标就是<ul>元素本身,并且Event对象不包含其它信息了。
- 再接着,在<ul>元素的子节点(当然要看被删除节点是否有子节点,如果没有,该行当没说。)<li>元素上也触发DOMNodeRemovedFromDocument事件,这次该事件的目标就是"#text",因为<li>元素包含的是文本内容。
- 随着在其父节点上(document.body)上触发DOMSubtreeModified事件,该事件的目标就是document.body。
- 最后,经过以上事件处理程序的操作,将<ul>元素节点从其父元素中删除。
- 首先会触发DOMNodeInsered事件,该事件的目标是被插入的节点(event.target),而event.relatedNode包含一个父节点的引用。在这个事件触发时,该节点已经被插入到文档中了。这个事件有冒泡,所以可以在DOM的任何层次上处理(也就是说,可以在DOM结构的任何层次上创建该事件的处理程序)。
- 接着会在新插入的节点上触发DOMNoeInseredIntoDocument事件。该事件不会冒泡,所有需在该节点被插入之前为它添加事件处理程序(也就是说只能新插入的节点上创建处理程序),该事件的目标就是这个新插入的节点,除此之外Event对象不包含其它事件信息。
- 最后在新插入的节点的父节点上触发DOMSubtreeModefied事件,该事件不包含任何有关事件的信息。
<!doctype html>
<html lang="zh-en">
<head>
<meta charset="utf-8">
<title>变动事件之删除节点操作</title>
<style></style>
</head>
<body>
<ul id="myList">
<li>li 1</li>
<li>li 2</li>
<li>li 3</li>
<li>li 4</li>
</ul>
<script>
window.onload = function (e) {
//通过ID获取ul元素的引用
let list = document.querySelector("#myList");
//创建一个新子节点,并添加内容。
let item = document.createElement("li");
item.innerHTML = "li 5";
/*首先是触发DOMNodeInserted事件,event.relateNode包含对一个父
节点的引用(即<ul>)*/
item.addEventListener("DOMNodeInserted", function (e) {
console.log(e.type); //DOMNodeInserted
console.log(e.target); // <li>...</li>
console.log(e.relateNode); //undefined
console.log(list.parentNode);
//<body>...</body> 在文档中创建的节点,开始时其父节点为<body>
});
//接着在新节点上触发DOMNodeInsertedIntoDocument事件
item.addEventListener("DOMNodeInsertedIntoDocument",
function(e) {
console.log(e.type); //DOMNodeInsertedIntoDocument
console.log(e.target); //<li>...</li>
});
/*随之触发DOMSubtreeModifined事件,该事件的目标是新插入节点的
父节点(即<ul>)此时Event对象不会包含任何有关事件的信息,所以
以下的内容不会返回。*/
document.addEventListener("DOMSubtreeModified", function (e) {
console.log(e.type);
console.log(e.target);
});
//设置以上事件处理程序之后,将新节点插入到文档中(即父节点中)。
list.appendChild(item);
//新节点插入到某个节点中,其父节点为某个节点。
console.log(item.parentNode); // <ul>...</ul>
}
</script>
</body>
</html>
Version:0.9 StartHTML:0000000105 EndHTML:0000022881 StartFragment:0000000141 EndFragment:0000022841
7⃣️ TML5事件
<!doctype html>
<html lang="zh-en">
<head>
<meta charset="utf-8">
<title>contextmenu事件</title>
<style>
#myDiv {
width: 200px;
height: 100px;
border: 1px solid blue;
}
#myMenu {
position: absolute;
visibility: hidden;
width: 185px;
height: 25px;
background-color: silver;
}
#myMenu li {
float: left;
list-style: none;
}
</style>
</head>
<body>
<div id="myDiv">文章内容</div>
<ul id="myMenu">
<li>首页</li>
<li>上一页</li>
<li>下一页</li>
<li>尾页</li>
</ul>
<script>
window.onload = function (e) {
let div = document.querySelector("#myDiv");
let menu = document.querySelector("#myMenu");
//添加contextmenu事件处理程序,自定义鼠标右键的上下文菜单
div.addEventListener("contextmenu", function (e) {
//阻止鼠标右键的默认行为(按鼠标右键有默认的菜单栏)
e.preventDefault();
//上下文菜单栏会出现在鼠标点击的位置
menu.style.left = e.clientX + "px";
menu.style.top = e.clientY + "px";
//点击鼠标显示菜单栏
menu.style.visibility = "visible";
});
//单击鼠标左键,隐藏自定义菜单栏。
document.addEventListener("click", function (e) {
menu.style.visibility = "hidden";
});
};
</script>
</body>
</html>
window.onbeforeunload = function (e) {
let message = "确定要离开页面吗";
return message;
};
window.addEventListenter("DOMContentLoaded", function () {
alert("用户早点与浏览器交互");
});
- uninitialized(未初始化):对象存在但未初始化。
- loading:对象正在加载数据。
- loaded:对象已经加载完数据。
- interactive:可以操作对象了,但未完全加载。
- compelete:对象已经加载完毕。
8⃣️ 拖放事件
<img id="dragImg" draggable="true" />
document.getElementById("dragImg").addEventListener("dragstart",
function(event) {
event.dataTransfer.setData("Text",ev.target.id);
}, false);
<div id="dragTarget"></div>
document.getElementById("dragTarget").addEventListener("dragenter",
function(event) {
// 阻止浏览器默认事件
event.preventDefault();
}, false);
document.getElementById("dragTarget").addEventListener("dragover",
function(event) {
// 阻止浏览器默认事件
event.preventDefault();
}, false);
document.getElementById("dragTarget").addEventListener("drop",
function(event) {
event.preventDefault();
let data=event.dataTransfer.getData("Text");
event.target.appendChild(document.getElementById(data));
}, false);
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
#dragTarget {
width:488px;
height:70px;
padding:10px;
border:1px solid #aaaaaa;}
</style>
<script type="text/javascript">
function allowDrop(ev){
ev.preventDefault();
}
function drag(ev){
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev){
ev.preventDefault();
let data=ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>
<p>please drop the picture to the box!</p>
<div id="dragTarget" ondrop="drop(event)"
ondragover="allowDrop(event)"></div>
<br />
<img id="dragImg"
src="http://www.w3school.com.cn/i/w3school_banner.gif"
draggable="true" ondragstart="drag(event)" />
</body>
</html>
拖放的相关事件
事件 | 产生事件的元素 | 描述 |
---|---|---|
dragstart | 被拖放的元素 | 开始拖放操作 |
drag | 被拖放的元素 | 拖放过程中 |
dragenter | 拖放过程中鼠标经过的元素 | 被拖放元素开始进入本元素范围内 |
dragover | 拖放过程中鼠标经过的元素 | 被拖放元素正在本元素范围内移动 |
dragleave | 拖放过程中鼠标经过的元素 | 被拖放元素离开本元素范围 |
drop | 拖放的目标元素 | 有其他元素被拖放到本元素中 |
dragend | 拖放的目标元素 | 拖放操作结束 |
DataTransfer属性
属性 | 描述 |
---|---|
dropEffect | 表示拖放操作的视觉效果,允许对其进行值的设定。该效果必须 在用effectAllowed属性指定的允许的视觉效果范围内,允许指 定的值有:none、copy、link、move。 |
effectAllowed | 用来指定当元素被拖放时所允许的视觉效果。可以指定的值有: none、copy、copyLink、copyMove、link、linkMove、all、 uninitialize。 |
files | 返回表示被拖拽文件的 FileList。 |
types | 存入数据的MIME类型。如果任意文件被拖拽,那么其中一个类 型将会是字符串”Files”。 |
DataTransfer方法
方法 | 描述 |
---|---|
void setData(DOMString format, DOMString data) | 向DataTransfer对象存入数据。 |
DOMString getData(DOMString data) | 读取DataTransfer对象中的数据。 |
void clearData(DOMString format) | 清除DataTransfer对象中的数据。如 果省略参数format,则清除全部数 据。 |
void setDragImage(Element image, long x, long y) | 用img元素来设置拖放图标。 |
注册事件处理程序
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>test</title>
<style type="text/css">
#div1{width: 300px;
height: 300px;
background: red;
overflow:hidden;}
#div2{margin:50px auto;
width: 200px;
height: 200px;
background:green;
overflow:hidden;}
#div3{margin:50px auto;
width: 100px;
height: 100px;
background:blue;}
</style>
</head>
<body>
<div id="div1">div1
<div id="div2">div2
<div id="div3">div3</div>
</div>
</div>
<script type="text/javascript">
let div1 = document.getElementById('div1');
let div2 = document.getElementById('div2');
let div3 = document.getElementById('div3');
div1.onclick = function(){
console.log('div1');};
div2.onclick = function(){
console.log('div2');
};
div3.onclick = function(){
console.log('div3');
};
div1.onclick = function(){ /*覆盖前面的*/
console.log('div11111');
};
div1.onClick = function(){ /*大写不会识别出来*/
console.log('DIV11111');
};
</script>
</body>
</html>
- 因为JavaScript是严格区分大小写的,所以,这种形式下属性名只能按规定小写;
- 若给同一元素对象写多个onclick事件处理属性,后面写的会覆盖前面的(ps:这就是在修改一个对象属性的值,属性的值是唯一确定的);
- 这种形式也是在事件冒泡过程中注册事件处理程序的。
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>test</title>
<style type="text/css">
#div1{width: 300px;
height: 300px;
background: red;
overflow:hidden;}
#div2{margin:50px auto;
width: 200px;
height: 200px;
background:green;
overflow:hidden;}
#div3{margin:50px auto;
width: 100px;
height: 100px;
background:blue;}
</style>
</head>
<body>
<!--HTML中不区分大小写-->
<div id="div1" onClick="console.log('div1');">div1
<div id="div2" oNClick="console.log('div2');">div2
<!--元素的多个onclick事件处理属性只执行第一个-->
<div id="div3" onclick="console.log('div3');"
onclick="console.log('div3333');">div3</div>
</div>
</div>
<script type="text/javascript"></script>
</body>
</html>
- 因为HTML里面不区分大小写,所以这里事件处理程序属性名大写、小写、大小混写均可,属性值就是相应事件处理程序的JavaScript代码;
- 若给同一元素写多个onclick事件处理属性,浏览器只执行第一个onclick里面的代码,后面的会被忽略;
- 这种形式是在事件冒泡过程中注册事件处理程序的。
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>test</title>
<style type="text/css">
#div1{width: 300px;
height: 300px;
background: red;
overflow:hidden;}
#div2{margin:50px auto;
width: 200px;
height: 200px;
background:green;
overflow:hidden;}
#div3{margin:50px auto;
width: 100px;
height: 100px;
background:blue;}
</style>
</head>
<body>
<div id="div1" >div1
<div id="div2" >div2
<div id="div3" >div3</div>
</div>
</div>
<script type="text/javascript">
let div1 = document.getElementById('div1');
let div2 = document.getElementById('div2');
let div3 = document.getElementById('div3');
div1.addEventListener('click', function(){
console.log('div1-bubble'); },false);
div2.addEventListener('click', function(){
console.log('div2-bubble'); },false);
div3.addEventListener('click', function(){
console.log('div3-bubble'); },false);
div3.addEventListener('click', function(){
console.log('div3-bubble222'); }, false);
div1.addEventListener('click', function(){
console.log('div1-capturing');}, true);
div2.addEventListener('click', function(){
console.log('div2-capturing');}, true);
div3.addEventListener('click', function(){
console.log('div3-capturing');}, true);
</script>
</body>
</html>
- addEventListener()第三个参数可以忽略;
- 通过addEventListener()方法给同一对象注册多个同类型的事件,并不会发生忽略或覆盖,而是会按顺序依次执行;
div1.addEventListener('click', div1BubbleFun, false);
div1.removeEventListener('click', div1BubbleFun, false);
function div1BubbleFun(){
console.log('div1-bubble');
};
let div1 = document.getElementById('div1');
div1.attachEvent('onclick', div1BubbleFun);
function div1BubbleFun(){
console.log('div1-bubble');
}
div1.detachEvent('onclick', div1BubbleFun);
事件处理程序的调用
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>test</title>
<style type="text/css">
#div1{width: 300px;
height: 300px;
background: red;
overflow:hidden;}
</style>
</head>
<body>
<div id="div1">div1</div>
<script type="text/javascript">
let div1 = document.getElementById('div1');
if(div1.addEventListener){
div1.addEventListener('click', div1Fun, false);
}else if(div1.attachEvent){
div1.attachEvent('onclick', div1Fun);
}
function div1Fun(event){
event = event || window.event;
let target = event.target || event.srcElement;
console.log(event.type);
console.log(target);
}
</script>
</body>
</html>
- 事件处理程序中this指向这个元素本身:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>test</title>
<style type="text/css">
#div1{width: 300px;
height: 300px;
background: red;
overflow:hidden;}
</style>
</head>
<body>
<div id="div1" onclick="console.log('html:');
console.log(this);">div1</div>
<script type="text/javascript"></script>
</body>
</html>
- 在<body></body>中 添加如下script代码,代码中的this也指向元素本身,但是会覆盖前面注册的事件处理程序:
<script type="text/javascript">
let div1 = document.getElementById('div1');
div1.onclick = function(){
console.log('div1.onclick:');
console.log(this);
};
</script>
- 在<script></script>标签中继续添加如下代码,代码中的this同样指向元素本身,并且不会覆盖前面注册的事件处理程序:
div1.addEventListener('click', function(){
console.log('div1.addEventListener:');
console.log(this);
}, false);
- 在<script></script>标签中添加如下代码,代码中的this指向的则是全局对象window,并且该方法也不会覆盖前面注册的事件处理程序:
div1.attachEvent('onclick', function(){
console.log('div1.attachEvent:');
console.log(this === window);
});
- 通过HTML属性注册的处理程序和通过设置对象属性的处理程序一直优先调用;
- 使用addEventListener()注册的处理程序按照它们的注册顺序依次调用;
- 使用attachEvent()注册的处理程序可能按照任何顺序调用,所以代码不应该依赖于调用顺序;
function cancelHandler(event){
let event = event || window.event;
if(event.preventDefault){
event.preventDefault();
}
if(event.returnValue){
event.returnValue = false;
}
return false;
}
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>test</title>
<style type="text/css">
#div1{width: 300px;
height: 300px;
background: red;
overflow:hidden;}
#div2{margin:50px auto;
width: 200px;
height: 200px;
background: green;
overflow:hidden;}
#div3{margin:50px auto;
width: 100px;
height: 100px;
background: blue;}
</style>
</head>
<body>
<div id="div1">div1
<div id="div2">div2
<div id="div3">div3</div>
</div>
</div>
<script type="text/javascript">
let div1 = document.getElementById('div1');
let div2 = document.getElementById('div2');
let div3 = document.getElementById('div3');
div1.onclick = function(){
console.log('div1');
};
div2.onclick = function(){
console.log('div2');
};
div3.onclick = function(event){
stopEventPropagation(event);
console.log('div3');
};
function stopEventPropagation(event){
let event = event || window.event;
if(event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble = true;
}
}
</script>
</body>
</html>