事件流
事件流
:描述的是从页面接收事件的顺序;
浏览器事件
:如单击事件,当你单击按钮的同时,你也单击了按钮的容器元素,甚至也单击整个页面.
- 事件冒泡 ( IE 事件流)
- 事件开始时由最
具体的元素接收,然后逐级向上传播到不具体的节点
<!DOCTYPE html>
<html>
<head>
<title>Event Bubbling Example</title>
</head>
<body>
<div id="myDiv">Click Me</div>
</body>
</html>
- 如果
单击了页面的div元素,事件的传播顺序为:div---->body---->html----->document
- 事件捕获(Netscape)
不太具体的节点应该更早接收到事件,而最具体的节点最后接收到事件。- 此时上面的单击事件的
传播顺序为:document----->html----->body------>div
- Dom事件流
DOM2级事件规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段- 此时上面的单击事件的传播顺序为:(
document----->html----->body) 事件捕获阶段------> (div)处于目标阶段----> (body---->html----->document)事件冒泡阶段
事件处理程序
事件就是用户或浏览器自身执行的某种动作: 如click(单击事件)
响应某个事件的函数就叫做事件处理程序(或事件侦听器)
事件
处理程序的名字以"on"开头,如onclick,onload
Html事件处理程序
- 元素中的事件
属性特性值为js代码,一般不采用。
<input type="button" value="Click Me" onclick="alert('Clicked')" />
- 元素中的事件
属性特性值为:要执行的具体操作(函数调用)------->这样会创建一个封装着元素属性值的函数,该函数中有一个局部变量 event,也就是事件对象。访问局部变量event和元素属性值:
//调用局部变量event
<input type="button" value="Click Me" onclick="alert(event.type)"> //打印结果click
//调用元素属性值
<input type="button" value="Click Me" onclick="alert(this.value)"> //打印结果 Click Me
//调用封装函数内的局部变量event和元素属性值
<body>
<input type="button" value="hahhahhah" onclick="test(event,value)">点击这里 </input>
<script>
function test(event,value) {
console.log(event.type+""+value);
}
</script>
</body>
动态创建的封装函数通过with扩充作用域若是普通元素如:
<input type="button" value="Click Me" onclick="alert(this.value)">
动态函数扩充作用域:
function(){
with(document){
with(this){
//元素属性值
}
}
}
若是表单元素如:
<form method="post">
<input type="text" name="username" value="">
<input type="button" value="Echo Username" onclick="alert(username.value)">
</form>
动态函数扩充作用域:
function(){
with(document){
with(this.form){
with(this){
//元素属性值
}
}
}
}
Dom0级事件处理程序
<button id="myBtn">点击</button>
<script>
var btn = document.getElementById("myBtn");
btn.onclick = function () {
// this为当前元素引用,event为局部变量
alert(this.id+""+event.type); //"myBtnclick"
btn.onclick = null;
};
document.body.appendChild(btn);
</script>
this为绑定的元素对象引用- 将如
onclick等事件处理程序设置为null就能取消单击事件
Dom2级事件处理程序
- 使用
addEventListener()和removeEventListener()指定和删除事件处理程序-----> 有三个参数:事件名,处理函数,布尔值(捕获阶段处理用true,冒泡阶段处理用false) - 要使
移除的是同一个事件处理函数,必须传的是函数变量,而不是匿名函数(会导致add和remove的不是同一个)
var btn = document.getElementById("myBtn");
var handler = function(){
alert(this.id);
};
btn.addEventListener("click", handler, false);
//这里省略了其他代码
btn.removeEventListener("click", handler, false);
IE事件处理程序
IE实现了与DOM中类似的两个方法:attachEvent()和detachEvent()。这两个方法接受相同的两个参数:事件名称与处理函数。IE只支持事件冒泡- 事件名前需要加
on
var btn = document.getElementById("myBtn");
var handler = function(){
alert("Clicked");
};
btn.attachEvent("onclick", handler);
//这里省略了其他代码
btn.detachEvent("onclick", handler);
跨浏览器的事件处理程序
var EventUtil = {
addHandler: function (element, type, handler) {
//判断是否是dom2级的
if (element.addEventListener) {
element.addEventListener(type, handler, false);
// 判断是否是 IE
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
}
//最后就是dom0级的
else {
element["on" + type] = handler;
}
},
removeHandler: function (element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
}
};
例子:
var btn = document.getElementById("myBtn");
var handler = function(){
alert("Clicked");
};
EventUtil.addHandler(btn, "click", handler);
//这里省略了其他代码
EventUtil.removeHandler(btn, "click", handler);
事件对象
常见的属性和方法:
preventDefault():取消事件的默认行为 ------->defaultPrevented来判断是否已经取消(Boolean值)
stopPropagation():取消事件的进一步捕获或冒泡-------->bubbles来判断是否已经取消
target:获取事件的目标对象(Element)
detail:事件的详细信息
type: 被触发的事件类型
等等
统一处理多个事件:
var btn = document.getElementById("myBtn");
var handler = function(event){
switch(event.type){
case "click":
alert("Clicked");
break;
case "mouseover":
event.target.style.backgroundColor = "red";
break;
case "mouseout":
event.target.style.backgroundColor = "";
break;
}
};
btn.onclick = handler;
btn.onmouseover = handler;
btn.onmouseout = handler;
跨浏览器的事件:
var EventUtil = {
addHandler: function(element, type, handler){
//省略的代码
},
getEvent: function(event){
// event为false时去获取IE的事件对象window.event
return event ? event : window.event;
},
getTarget: function(event){
//IE的目标对象event.srcElement
return event.target || event.srcElement;
},
preventDefault: function(event){
if (event.preventDefault){
event.preventDefault();
}
else {
//IE的取消默认事件
event.returnValue = false;
}
},
removeHandler: function(element, type, handler){
//省略的代码
},
stopPropagation: function(event){
if (event.stopPropagation){
event.stopPropagation();
}
else {
//IE的取消冒泡
event.cancelBubble = true;
}
}
};
事件委托
1. 事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件.
// html
// li 会冒泡到 ul,还可以在更上层的元素定义处理程序
<ul id="myLinks">
<li id="goSomewhere">Go somewhere</li>
<li id="doSomething">Do something</li>
<li id="sayHi">Say hi</li>
</ul>
// js
var list = document.getElementById("myLinks");
EventUtil.addHandler(list, "click", function(event){
event = EventUtil.getEvent(event);
//获取目标对象element
var target = EventUtil.getTarget(event);
//通过目标对象的id来判断做什么处理
switch(target.id){
case "doSomething":
document.title = "I changed the document's title";
break;
case "goSomewhere":
location.href = "http://www.wrox.com";
break;
case "sayHi":
alert("hi");
break;
}
});
- 移除事件处理程序,除了使用
removeChild()和replaceChild()方法,更多的使用用innerHTML```` 替换页面中某一部分,但要注意在替代时需使原先node绑定事件为null.
<body>
<div id="myDiv">
<input type="button" value="Click Me" id="myBtn">
</div>
<script type="text/javascript">
var btn = document.getElementById("myBtn");
btn.onclick = function(){
//先执行某些操作
btn.onclick = null; //移除事件处理程序
//此时button按钮被替换成Processing...文本
document.getElementById("myDiv").innerHTML = "Processing...";
};
</script>
</body>