event 事件1

时间:2024-03-25 20:06:38

1、事件流

1.1 事件冒泡

IE8- 浏览器支持的事件流是事件冒泡。事件冒泡是事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点(文档)的过程。

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="myDiv">Click me </div>
</body>
</html>

在上面的HTML页面中,如果点击了页面中的 div#myDiv ,那么事件就会按照如下顺序冒泡:div --> body --> html -->document。也就是说,click 事件在这些元素上都会发生。

所有现代浏览器都支持事件冒泡,IE9+、Firefox、Chrome、Safari 会将事件一直冒泡到 window 对象。

1.2 事件捕获

事件捕获与事件冒泡过程相反。事件捕获是由不太具体的节点先接收到事件,而最具体的节点最后接收到事件,由上而下触发事件。

以上面的HTML页面为例,如果点击了页面中的 div#myDiv ,那么事件就会按照如下顺序捕获触发:document --> html --> body -->div。

IE9+、Firefox、Chrome、Safari 都支持事件捕获,并且是由 window 对象开始捕获事件的。

1.3 DOM事件流

“DOM2级事件”规定事件流包括三个阶段,其顺序是:事件捕获阶段、处于目标阶段、事件冒泡阶段。

“DOM2级事件”规定要求捕获阶段不会涉及事件目标,但 IE9+、Firefox、Chrome、Safari、Opera9.5+ 都会在捕获阶段和冒泡阶段触发目标对象上的事件,即有两此处理目标对象事件的机会。IE8- 不支持DOM事件流。

2、事件处理程序

事件是用户或者浏览器自身执行的某个动作,诸如,click、load、mouseover等。事件处理程序(事件侦听器)是响应事件的函数,以“on“ 开头。为事件指定处理程序的方式有多种。

2.1 HTML 事件处理

每个元素值得每种事件,都可以使用一个与相应事件处理程序同名的HTML特性来指定。这个特性的值是能够执行的 JavaScript 代码。且这个值不能使用未经转义的HTML语法字符,如:&、”“、<、>等,如果要使用这些字符,需要使用转义值。

这样指定事件处理程序会创建一个封装着元素属性值的函数,这个函数有一个event变量指向事件对象,而且在这个函数内部,this 指向目标元素。这个函数扩展了它的作用域,可以访问document对象以及该元素本身成员。如果当前元素是一个表单元素,则作用域还会包含表单元

    <button onclick="alert('&quot;clicked&quot;')">点我</button>  <!--在此不能直接使用双引号("") -->
<button onclick="showMessage()">点我</button> <!--可以访问全局作用域中的函数 -->
<button value="hello" onclick="alert(this.value +' '+event.type)">点我</button> <!--暗中包含 event事件对象 和 this(目标元素) -->
<button id="helloid" onclick="alert(this.id +' '+event.type)">点我</button> <!--可以 this.attr 访问元素的属性 -->
<button value="hello" onclick="alert(value +' '+event.type)">点我</button> <!--直接访问元素的属性,button在IE7-中 js访问的value值是button的文本值,其他浏览器则是value特性的值-->
<button value="hello" onclick="showMessage(event,this)">点我</button> <!--传递参数 event 和 this -->
<input type="button" value="hello" onclick="showMessage(event,this)"/> <!-- -->
<form action="">
<input type="text" name="username" value="">
<input type="button" value="echo UserName" onclick="alert(username.value)"> <!--直接访问form表单的其他表单元素 -->
</form>
function showMessage(event,element){
console.log(event.type);
console.log(element.value);

所有现代浏览器都支持这种方式添加事件处理程序。

2.2 DOM0 级事件处理程序

通过JavaScript指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性,会覆盖HTML特性指定的事件处理程序。

每个元素(包括 window 和 document)都有自己的事件处理程序属性,通常是小写的,如 onclick。

使用DOM0 级方法指定的事件处理程序被认为是元素的方法,所以事件处理程序是在元素的作用域中运行的,即程序中 this 指向当前元素。DOM0的事件处理程序是在事件冒泡阶段被处理的。

var btn = document.getElementById("myBtn");
btn.onclick = function(){ // 覆盖HTML 特性指定的事件处理程序
alert(this.id); // this 指向btn
} btn.onclick = null; // 删除事件处理程序

所有现代浏览器都支持这种方式。

2.3 DOM2 级事件处理程序

“DOM2 级事件”定义了两个方法,用于增加、删除事件处理程序的操作,addEventListener(eventType, handler,  notBubble),removeEventListener(eventType, handler,  notBubble),所有节点都包含这两个方法。

eventType:事件类型,"click"、"load"等;handler:事件处理函数;notBubble:是否在冒泡阶段处理,true(捕获阶段调用事件处理程序),false(冒泡阶段处理事件)。

使用 addEventListener() 可以添加多个事件处理程序,并按照添加的顺序执行,添加的事件处理程序是在元素的作用域中运行的,即程序中 this 指向当前元素。removeEventListener()不能移除用匿名函数添加的事件处理程序

function showMessage(){
console.log("third event process");
} var btn = document.getElementById("mybtn");
var btn2 = document.getElementById("mybtn2");
var btn3 = document.getElementById("mybtn3"); btn.addEventListener("click",function(){ // 添加匿名处理函数,不能被移除; 第二个执行
console.log("another event process");
console.log(this.id); // this 指向当前元素
},false); 

btn.onclick = function(){  //第一个执行

    console.log(this.id);
} btn.addEventListener("click",showMessage,false); // 添加命名处理函数,可以被移除;第三个执行 btn2.onclick = function () {
btn.onclick = null; // 删除事件处理程序,使用addEventListener()添加的处理程序仍然存在
}
btn3.onclick = function () {
btn.removeEventListener("click",showMessage,false); // 删除事件处理程序
}

Chrome、Firefox、Safari、Opera、IE9+ 支持 addEventListener(),removeEventListener()

2.4  IE 事件处理程序

IE10- 实现了 attachEvent(eventType,handler),detachEvent(eventType,handler),来添加、去除事件处理程序,其中evenType是包含 "on"的,如"onclick"。IE11不支持。

因为IE8- 只支持事件冒泡,所以使用 attachEvent() 添加事件处理程序,会添加到事件冒泡阶段,并且事件处理函数会在全局作用域中执行,即 this 指向 widow 对象。也可添加多个事件处理程序,但IE8-按照以与添加顺序相反的顺序执行事件处理函数,而IE9、IE10 按照正序执行

function showMessage(){
console.log("third event process");
} var btn = document.getElementById("mybtn");
var btn2 = document.getElementById("mybtn2");
var btn3 = document.getElementById("mybtn3"); btn.attachEvent("onclick",function(){ // IE8- 第三个执行,IE9、IE10第二个执行
console.log("another event process");
console.log(this == window); //true,事件添加 this 指向 window 对象
});

btn.onclick = function(){     // 第一个执行
    console.log(this.id);
}
btn.attachEvent("onclick",showMessage); // IE8- 第二个执行,IE9、IE10第三个执行 btn2.onclick = function () { btn.onclick = null; // 删除事件处理程序
}
btn3.onclick = function () { btn.detachEvent("onclick",showMessage); // 删除事件处理程序
}

      注意:在一个事件有多个处理程序时,如果其中一个处理程序某处发生错误了,只会影响该处理程序的后面的代码,并不影响其他的事件处理程序的执行,以及事件传播,不管这些事件程序是以什么方法添加的。

3、事件对象

在触发DOM上的某个事件时,会产生一个事件对象event,包含着所有与事件有关的信息。只有在事件处理程序执行期间,event 对象才会存在,事件处理程序执行完后,event对象就会被销毁。

3.1 DOM中的事件

兼容DOM事件(包含DOM0和DOM2)的浏览器会将一个 event 对象传入到事件处理程序中。以HTML特性添加的事件处理程序也存在 event 对象,并且和DOM事件对象具有一样的操作。

DOM事件对象的属性和方法:

属性/方法 类型 读/写 说明
bubbles Boolean 只读 表明事件是否冒泡
cancelable Boolean 只读 表明是否可以取消事件的默认行为
currentTarget Element 只读 事件处理程序当前正在处理事件的那个元素,等于 this 对象
defaultPrevented Boolean 只读 为true表示已经调用了preventDefault()
detail Integer 只读 与事件相关的细节信息
eventPhase Integer 只读 调用事件处理程序的阶段,1表示捕获阶段,2表示处于目标阶段,3表示冒泡阶段
preventDefault() Function 只读 取消事件的默认行为,如果cancelable是true,则可以使用这个方法
stopImmediatePropagation() Function 只读 取消时间进一步捕获或冒泡,同时阻止任何事件处理程序被调用(DOM3级)
stopPropagation() Function 只读 取消事件进一步捕获或冒泡。如果bubbles为true,则可使用这个方法
target Element 只读 事件的目标元素
trusted Boolean 只读 为true表示事件是浏览器生成的,为false,表示事件是有开发者通过JavaScript创建的(DOM3级)
type String 只读 事件的类型
view AbstructView 只读 与事件关联的抽象视图,等同于发生事件的window对象
var btn = document.getElementById("mybtn");
var btn2 = document.getElementById("mybtn2");
var link = document.getElementById("myLink"); btn.onclick = function(event){
console.log(event.type); // "click"
console.log(event.currentTarget == this); //true
console.log(event.target == this); // true
console.log(event.eventPhase); //
}
btn.addEventListener("click",function (event) {
console.log(event.type); // "click"
console.log(event.eventPhase); //
},false); document.body.onclick = function(event){ // 事件冒泡到body console.log(event.currentTarget == document.body); // true
console.log(this == document.body); // true
console.log("body-bubbles:"+event.target.id); //
console.log(event.eventPhase); //
} document.body.addEventListener("click",function(event){
console.log("body-capture: "+event.type +",target: "+ event.target.id);
//event.stopPropagation(); // 如果在捕获阶段阻止事件传播,目标元素定义的事件处理程序就不会执行了
console.log(event.eventPhase); //
},true); var handler = function(event){
switch(event.type){
case "click":
console.log("clicked");break;
case "mouseover":
event.target.style.backgroundColor = "red";break;
case "mouseout":
event.target.style.backgroundColor = "";break;
}
} btn2.onclick = handler;
btn2.onmouseover = handler;
btn2.onmouseout = handler; // <a href="https://www.baidu.com" target="_blank" id="myLink" onclick="event.preventDefault();">baidu</a>
link.onclick = function(event){
event.preventDefault();
}

3.2 IE中的事件对象

1)DOM0级添加的事件处理程序,事件对象是作为 window 对象的一个属性(event)而存在。在IE9+中事件对象对象也会作为参数传入事件处理程序函数(其实是IE9+开始支持DOM事件对象)。

2)attachEvent() 添加的,事件对象对象作为参数传入事件处理程序函数,同时也可以通过 window.event 得到事件对象

3)通过 HTML 指定的事件处理程序,也可以通过 event 变量访问事件对象(与DOM中一样)

IE事件对象的属性和方法:

属性/方法 类型 读/写 说明
cancelBubble Boolean 读/写 默认值为false,将其设置为true就取消事件传播
returnValue Boolean 读/写 默认值为true,设置为false取消事件的默认行为
scrElement Element 只读 事件的目标元素
type String 只读 事件类型
var btn = document.getElementById("mybtn");
var link = document.getElementById("myLink");
btn.attachEvent("onclick",function(event){
console.log(this == window); //true
console.log(event.srcElement.tagName); //
console.log(window.event.srcElement.tagName); // event 和 window.event 是不相等的
}); btn.onclick = function(event){
console.log(this == window.event.srcElement); // true
事件对象
console.log(event); // 在IE8- 中, 参数 event 的值是undefined
console.log(window.event.type); //click, 所有IE 都支持,新版本的Chrome、edge也支持,Firefox不支持
console.log(event == window.event); // false, IE9+ 开始支持DOM 事件对象,但参数event 和 原本 window.event 不是同一个事件对象 event.stopPropagation(); // 在IE9+ 中能运行。IE8-报错 event = window.event;
event.cancelBubble = true; // 阻止事件传播 } document.body.onclick = function(){ // 事件冒泡到body console.log("body clicked");
} link.onclick = function(event){ //在IE8- 中, 参数 event 的值是undefined
var event = window.event;
event.returnValue = false; // 阻止默认行为
}

4、事件类型