事件

JavaScript与HTML之间的交互是通过事件实现的。

事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。可以使用侦听器(或是处理程序)来预定事件,以便事件发生时执行相应的代码

IE9、Firefox、Opear、Safari和Chrome全部都已经实现“DOM2级事件”模块的核心部分。

一、事件流

事件流描述的是从页面接收事件的顺序。

事件发生时元素节点之间按照特定的顺序传播,这个过程即DOM事件流

事件流:点击了某个按钮也触发了这个按钮所在的区域,同时也触发了区域所在的页面。

DOM事件流分为三个阶段1、捕获阶段;2、当前目标阶段;3、冒泡阶段

例如:为div注册了一个点击事件:

  • 事件冒泡:IE最早提出,时间开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程;
  • 事件捕获:网景Netscape Communicator 最早提出,由DOM的最顶层节点开始,然后逐级向下传播到最具体的元素的接收过程。

注意:1、JS代码中只能执行捕获或是冒泡阶段的其中一个阶段

2、onclickattachEvent 只能得到冒泡阶段;

3、addEventListener(type,listener[,useCapture ])第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;如果是false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。

4、在实际开发中很少使用事件捕获,更加关注事件冒泡;

5、有些事件是没有冒泡的,比如:onblur、onfocus、onmouseenter、onmouseleave

6、事件冒泡有的时候会带来麻烦,有的时候又帮助会很巧妙的做某些事件。

(一)、事件冒泡

IE的事件流叫做事件冒泡(event bubbling)

冒泡的是事件,而不是事件的结果,每一层对同一个事件因为执行程序不同而有不同的反应。

事件冒泡:即事件最开始由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到最不具体的节点(文档)。

举个例子:我们向水里扔了一块石头,石头会有一个下降的过程,这个过程就可以理解为从顶层向事件发生的最具体的元素(目标点)的捕获的过程。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<button>click</button>
</div>
</body>
</html>

点击了click按钮,浏览器会认为点击了按钮的同时也点击了包含按钮的div,点了div后又认为点击了整个HTML,点了HTML又会认为点了整个document。

这个click事件传播的顺序:1、button;2、div;3、body;4、html;5、document

也就是说,click事件首先在<button>元素上发生,这个元素就是我们要单击的元素。然后,click事件沿着DOM树向上传播,在每一个节点上都会发生,直至传播到document对象。将这个过程叫做事件冒泡。

(二)、事件捕获

事件捕获:不太具体的节点,应该更早接收到事件,而最具体的节点最后接收到事件。(与事件冒泡截然相反)

事件捕获的用意在于在事件到达预定目标之前捕获它。

再举个例子:我们朝着水里面扔了一块石头,石头沉了下去,但是会产生泡泡,泡泡会在沉到水底的石头最低点(最具体的元素)之后漂浮到水面上,这个过程就相当于事件冒泡。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<button>click</button>
</div>
</body>
</html>

先是document,然后是HTML,再到body,然后是div容器,最后是click按钮(逐级向下)

单击<button>元素就会按照顺序触发click事件:1、document;2、html;3、body;4、div;5、button

二、事件对象

var div = document.getElementById('box');
div.onclick = function(event){ };

1、event在这里面就是事件对象,写到侦听函数的小括号() 里面,可以当做形参来看。

2、事件对象只有有了事件才会存在,事件对象是系统自动给我们创建的,不需要我们传递参数(事件对象必定和事件相关,如果没有事件它就不存在,有了事件就存在了)

3、事件对象是 跟事件相关的一系列相关数据的集合  ,比如说 鼠标点击里面就包含了鼠标相关的信息,如鼠标坐标;如果是键盘事件里面就包含了键盘事件的信息,比如判断用户按下了哪个键。

4、事件对象可以自己命名,比如 event、ee、aa

<body>
<div class="father">
<div class="son"></div>
</div>
<script>
var son = document.querySelector(".son");
son.addEventListener('click',function(event){
console.log(event);
})
</script>

为事件指定一个事件对象 event (事件对象中包含着与事件有关的信息),当我们使用console.log()打印出这个事件对象,展现的就是该事件所有相关信息。

事件目标是div,类名为son,事件类型为 click。

事件对象的兼容性方案:

事件对象本身的获取存在兼容性问题:(指定事件处理函数:addEventListenter()在IE8中不兼容)

1、标准浏览器中是浏览器给方法传递的参数,只需要形参e就可以获取到;

2、IE6、IE7、IE8中,浏览器不会给方法传递参数,如果需要的话,需要通过window.event中查找获取

解决:aa = aa || window.event;

直接打印事件对象的名称就会返回undefined

使用window.event来兼容IE的低版本的浏览器

var son = document.querySelector('.son');
son.onclick = function(aa){
//console.log(aa);
console.log(window.event);
//aa = aa || window.event;
//console.log(aa);
};

其他浏览器也可以正常解析 window.event 。有一种兼容性写法,在实际开发中并不需要过多的担心这个问题,直接按照正常情况来写就没有问题。

aa = aa || window.event;
console.log(aa);

三、常见事件对象的属性和方法

(一)事件对象属性和方法

事件对象属性方法 说明
e.target 返回触发事件的对象          标准
e.srcElement 返回触发事件的对象          非标准 IE6-8使用
e.type 返回事件的类型(比如 click、mouseover不带on)
e.cancelBubble 该属性阻止冒泡                 非标准 IE6-8使用
e.returnValue 该属性 阻止默认事件(默认行为) 非标准 IE6-8 使用,比如不让链接跳转               
e.preventDefault() 该方法 阻止默认事件(默认行为) 标准,比如不让链接跳转
e.stopPropagation()              阻止冒泡  标准

 注意:得先写事件对象,才能使用事件对象里面的属性。

(二)e.target 和 this 的区别

1、e.target 返回的是触发事件的对象(元素)目标;

2、this 返回的是绑定事件的对象;

区别:e.target  点击了哪个元素就返回那个元素;

this  绑定了哪个元素就返回哪个元素。那么就返回谁。

<body>
<div>12345</div>
<ul>
<li>aaa</li>
<li>aaa</li>
<li>aaa</li>
</ul>
<script>
var div = document.querySelector('div');
div.addEventListener('click',function(e){
console.log(e.target);
console.log(this);
});
</script>

 实例2:


给ul绑定了单击事件,那么this指向的就是ul

e.target  指向我们点击的那个对象(那个元素触发的对象),点击的是li,所以e.target 指向的就是 li

    var ul = document.querySelector('ul');
ul.addEventListener('click',function(e){
console.log(e.target);
console.log(this);
});

 浏览器兼容:

了解兼容性即可,e.target 适用于标准浏览器,e.srcElement 适用于非标准浏览器 (IE6~8浏览器)

跟 this 有个非常相似的属性  currentTarget ,不过这个 currentTarget 属性 IE6~8 不兼容。

<body>
<div>12345</div>
<ul>
<li>aaa</li>
<li>aaa</li>
<li>aaa</li>
</ul>
<script>
var div = document.querySelector('div');
div.onclick = function(e){
e = e || window.event;
var target = e.target ||
e.srcElement;
console.log(target);

}
</script>

 (三)阻止默认行为

属性:

1、e.type 返回事件类型

2、e.returnValue() 该属性 阻止默认事件(默认行为)非标准 IE6~8使用(例如 不让链接跳转)

3、e.preventDefault() 该方法 最值默认事件(默认行为)标准(例如 不让链接跳转)

<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> </style>
</head>
<body>
<div>123</div>
<a href="http://www.baidu.com">baidu</a>
<form action="http://www.baidu.com">
<input type="submit" value="submit" name="sub">
</form>
<script>
//常见事件对象的属性和方法
//1、返回事件类型
var div = document.querySelector('div');
div.addEventListener('mouseover',hs);
div.addEventListener('click',hs);
function hs(e){
console.log(e.type);
}
//阻止默认行为(事件)让链接不跳转,或是让提交按钮不提交
//DOM标准写法
var a = document.querySelector('a');
a.addEventListener('click',function(e){
//e.preventDefault();
});
//传统的注册方式
a.onclick = function(e){
//普通浏览器 e.preventDefault();方法
e.preventDefault();
//IE浏览器 IE6、7、8 e.returnValue;属性
e.returnValue;
//也可以使用 return false 也可阻止默认行为,没有兼容性问题,return后面的代码不会被执行,而且只限于传统的注册方式。
return false;
 alert(11111);
}
</script>
</body>
</html>

 1、事件处理程序

2、传统注册方式

e.preventDefault();    普通浏览器 e.preventDefault();方法

e.returnValue;   IE浏览器 IE678 e.returnValue;属性

return false;    也可以使用 return false 也可阻止默认行为,没有兼容性问题

四、事件处理程序

事件就是用户或浏览器自身执行的某种动作,例如 click、load和mouseover,这些都是事件的名字。

而响应某个事件的函数就叫做事件处理程序(或 事件侦听器)。

事件处理程序的名字以 "on" 开头,因此click事件处理程序就是 onclick ,load事件的事件处理程序就是onload。

为事件指定程序有三种方式:

(一)HTML事件处理程序

某个元素支持的每种事件,都可以使用一个与相应事件处理程序同名的HTML特性来指定。这个特性的值应该是应该能够执行的JavaScript代码。

实例1:


要在按钮被单击时执行一些JS代码

<button onclick="alert('clicked')">click</button>

表现效果:单击这个按钮时就会显示出一个警告框

这个操作是通过制定onclick特性并将一些JS代码作为它的值来定义的。

由于这个值是JavaScript ,因此不能再其中使用未经转义的HTML语法字符,例如和号(&)、双引号(" ")、小于号(<)、大于号(>)。

为了避免使用HTML实体,这里使用了单引号,如果想使用双引号,可以使用(&quot;  双引号的转义字符)

<button onclick="alert(&quot; clicked &quot;)">click</button>

 

实例2


在HTML中定义的事件处理程序可以包含要执行的具体动作,也可以调用在页面其他地方定义的脚本,如下例所示:

<button onclick="aa()">click</button>
<script>
function aa(){
alert("hello world!")
}
</script>

在这个例子中,单击按钮就会调用 aa() 函数。

这个函数是放在一个独立的 <script> 元素中定义的,当然也可以被包含在一个外部文件中。事件处理程序中的代码在执行时,有权访问全局作用域中的任何代码。

实例3


这样指定事件处理程序具有一些独到之处。这样会创建一个封装着元素属性值的函数,这个函数中有一个局部变量event,也就是事件对象。

<button onclick="alert(event.type)">click</button>

通过event变量,可以直接访问事件对象。无需自己定义,也不用从函数的参数列表中读取。

实例4


在这个函数内部,this值等于事件的目标函数

<span onmouseover="this.style.color='red'" >test</span>

this代表事件作用的这个标签本身(上例中this代表span标签本身)

(二)HTML0 级事件处理程序

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

每个元素(包括window 和 document)都有自己的事件处理程序属性,这些属性通常全部小写,例如onclick,将这种属性的值设置为一个函数,就可以指定事件处理程序

实例1:


 var bq = document.getElementById("bq");
bq.onclick = function(){
alert("click");
}

在这里,通过文档对象获得了一个按钮的id,然后为它指定了onclick事件处理程序。

注意:在这些代码运行以前不会指定事件处理程序,因此如果这些代码在页面中位于按钮后面,就有可能在一段时间内怎么单击都没有反应。

使用DOM0 级方法指定的事件处理程序被认为是元素的方法。因此,这时候的事件处理器是在元素的作用域中运行的程序中的this元素引用当前的元素;

实例2:


<input type="button" value="click" id="bq">
<script>
var bq = document.getElementById("bq");
bq.onclick = function(){
alert(this.id);
}
</script>

点击按钮显示的是元素的ID,这个ID是通过this.id取得的。不仅仅是ID,实际上可以在事件处理程序中通过 this 访问该元素的任何属性和方法。以这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。

删除事件处理程序

删除通过DOM0 级方法指定的事件处理程序,只需要将事件处理程序属性的值设置为null即可。将事件处理程序设置为null之后,再单击按钮将不会有任何动作发生。

bq.onclick = null;   //删除事件处理函数

注意:如果使用HTML指定事件处理程序,那么onclick属性的值就是一个包含着在同名HTML特性中指定代码的函数。而将相应的属性设置为null,也可以删除以这种方式指定的的时间处理函数。

(三)DOM2 级事件处理程序

DOM2 级事件定义了两个方法:指定事件处理函数:addEventListenter(); 和删除事件处理程序的操作:removeEventListener();

所有的DOM节点都包含这两个方法,并且都接受3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。

布尔值为true,表示在捕获阶段调用事件处理程序;

布尔值为false(不写默认就是false),表示在冒泡阶段调用事件处理程序;

(一)指定事件处理函数:addEventListenter()

实例1:


在按钮上为click事件添加事件处理程序

<input type="button" value="click" id="bq">
<script>
var bq = document.getElementById("bq");
bq.addEventListener("click",function(){
alert(this.id);},false);
</script>

上面这个例子中为按钮添加了 onclick 事件处理程序,并且这个事件处理程序会在冒泡阶段被触发(因为最后一个参数是false)。

和DOM0 级方法一样,这里添加的事件处理函数也是在其依附的元素的作用域中运行。

使用DOM2 级方法添加事件处理程序的主要好处是可以添加多个事件处理函数

实例2:


为bq添加多个事件处理函数

<input type="button" value="click" id="bq">
<script>
var bq = document.getElementById("bq");
bq.addEventListener("click",function(){
alert(this.id);},
false);
bq.addEventListener("click",function(){
alert("hello world !");},
false);
</script>

在这里为按钮添加了两个事件处理函数,两个事件处理函数会按照添加的先后顺序依次触发,因此在这里会先显示元素的ID,然后再显示" hello world !" 的提示信息。

实例3:


捕获阶段:如果addEventListener 的三个参数是 true ,那么就处于捕获阶段 document —> html —> body —> father —> son

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.father{width:100px;height:100px;background:#faa;margin:100px auto;}
.son{width:50px;height:50px;background:#aaf;margin:auto}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
var son = document.querySelector(".son");
son.addEventListener('click',function(){
alert('son');
},true)
var father = document.querySelector(".father");
father.addEventListener('click',function(){
alert('father');
},true)
</script>
</body>
</html>

点击子元素盒子,会先弹出 father警示框,再点击确认之后才会出现 son警示框。从上到下捕获。

 实例4:


冒泡阶段:如果addEventListener 的三个参数是 false,那么则处于冒泡阶段,son —> father —> body —> html—> document

<script>
var son = document.querySelector(".son");
son.addEventListener('click',function(){
alert('son');
},false)
var father = document.querySelector(".father");
father.addEventListener('click',function(){
alert('father');
},false)
</script>

现在处于冒泡阶段,先从son开始,点击son的时候son警示框先弹出,点击确定之后,继续向上冒泡,father里面也有一个侦听器,所以father警示框弹出。

(二)移除事件处理程序

通过  addEventListener(); 添加的事件处理程序只能使用  removeEventListener()  来移除;移除时传入的参数和添加程序处理程序时使用的参数相同。

这也意味通过 addEventListener() 添加的匿名函数(没有传入参数)将无法移除

实例3


 var bq = document.getElementById("bq");
bq.addEventListener("click",function(){
alert(this.id);},
false);
bq.removeEventListener("click",function(){//无用
alert(this.id);},
false);

在这个例子中,我们使用 addEventListener() 添加了一个事件处理函数,虽然调用了 removeEventListener() 时看似使用了相同的参数,但是实际上,第二个参数与传入的addEventListener() 中的参数是完全不同的参数。

实例4


传入removeEventListener() 中的事件处理程序参数 必须与传入addEventListener()中的相同

 var bq = document.getElementById("bq");
var handle = function(){
alert(this.id);
};
bq.addEventListener("click",handle,false);
bq.removeEventListener("click",handle,false);

将事件处理器写成这个样子没有问题,这只因为在addEventListener() removeEventListener() 中使用了相同的函数。

大多数情况,都是将事件处理程序添加到事件流的冒泡阶段,这样就可以最大限度上的兼容各种浏览器。最好只在需要在事件到达目标之前截获它的时候将事件处理程序添加到捕获阶段。

如果不是特别需要,不建议在事件捕获阶段注册事件处理程序。

IE9、FireFox、Safari、Chrome和Opera支持DOM2 级事件处理程序。

DOM事件处理函数的更多相关文章

  1. JavaScript移除绑定在元素上的匿名事件处理函数

    前言: 面试的时候有点蒙,结束之后想想自己好像根本就误解了面试官的问题,因为我理解的这个问题本身就没有意义.但是当时已经有一些思路,但是在一个点上被卡住. 结束之后脑子瞬间灵光,想出了当时没有迈出的那 ...

  2. javascript学习笔记(四):事件处理函数和动态创建html标记。

    1 HTML的事件属性  全局事件属性:HTML 4 增加了使事件在浏览器中触发动作的能力,比如当用户点击元素时启动 JavaScript. a. Window 事件属性,针对 window 对象触发 ...

  3. DOM事件处理有三个阶段

    DOM事件处理有三个阶段: 捕捉阶段(capture phase):从最上层元素,直到最下层(你点击的那个target)元素.路过的所有节点都可以捕捉到该事件. 命中阶段(target phase): ...

  4. W3C和IE中的事件处理函数

    在上一篇文章中提到了关于传统的JS中注册事件对象的一些缺点和问题,下面是关于DOM2级的现代事件绑定.本文中设计到的HTML文件在文章最后 一.W3C事件处理函数 “DOM2 级事件”定义了两个方法, ...

  5. js中关于事件处理函数名后面是否带括号的问题

    今天总结一个关于事件处理程序的小细节.首先回顾一下事件处理的一些概念. JS中的事件处理(事件绑定)就是让某种或某些事件触发某些活动.有两种常见的形式,分别是DOM Level 0 和DOM Leve ...

  6. 前端魔法堂:onsubmit和submit事件处理函数怎么不生效呢?

    前言  最近在用Polymer增强form,使其支持表单的异步提交,但发现明明订阅了onsubmit和submit事件,却怎么也触发不了.下面我们将一一道来. 提交表单的方式 表单仅含一个以下的元素时 ...

  7. jQuery总结--版本二 事件处理函数

    一:事件处理函数 (1) one(事件名称, fn) 仅对指定事件监听一次,监听事件只会执行一次 <!DOCTYPE html> <html> <head lang=&q ...

  8. 前端菜鸟学习之DOM事件处理

    一.事件处理程序 1.DOM0级事件处理程序:就是将一个函数赋值给一个事件处理程序属性,至今仍为现代所有浏览器所支持,主要得益于其跨浏览器的优势,要使用DOM0级事件 首先要得到操作对象的引用,具体实 ...

  9. React 学习(三) ---- state 和 事件处理函数

    在上两节中,我们讲述了props, 组件使用props进行渲染,但是这是一次性的, props渲染完成之后就不做任何事情了,但是现实中却不是这样的,当我们点击购物车上的加减按钮时,数量会自动加1或减1 ...

随机推荐

  1. Alias sample(别名采样)

    应用场景:加权采样,即按照随机事件出现的概率抽样 具体算法: 举例如上,随机事件出现的概率依次是1/2,1/3,1/12,1/12;记随机事件的个数为N,则所有事件概率乘以N后概率为2,4/3,1/3 ...

  2. 1.MySQL的基本使用

    数据库的操作: 1.Windows中如何使用CMD进入MySQL数据库:     1 Windows+R  -->  输入 cmd 运行     2 C:\Users\***>D:    ...

  3. python3 selenuim PC端使用chrome模拟手机进行H5自动化

    情况说明:初次在做PC端使用chrome进行H5自动化测试时,以为和app端自动化一样使用click()就可以对按钮进行点击,找了好几天也没有找到解决方法,有些人说是工程问题,有些人是使用微信进行H5 ...

  4. vue --》动态路由的实现 (根据用户的权限来访问对应的模块)

    为了设置用户的访问权限,所以在一个vue工程中,往往需要前端和后端开发人员共同配合设置动态路由, 进而实现根据用户的权限来访问对应的模块 1.首先在登录页面,前端跟据后端返回的路由信息进行配置,配置后 ...

  5. mysql——单表查询——聚合函数——示例

    ), km ), cj ) ); select * from score; ,); ,); ,); ,); ,); ,); ,); ,); ,); ,); ,); ,); ; 查询此同学的总成绩: ; ...

  6. 使用graphics.h来绘制图形

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. graphics.h是TC里面的图形库,如果要用的话应该用TC来编译.分为:像素函数.直线和线型函数.多边形函数.填充函数等.然而在我们使 ...

  7. [Python3] 031 常用模块 shutil & zipfile

    目录 shutil 1. shutil.copy() 2. shutil.copy2() 3. shutil.copyfile() 4. shutil.move() 5. 归档 5.1 shutil. ...

  8. 并发之AQS原理(二) CLH队列与Node解析

    并发之AQS原理(二) CLH队列与Node解析 1.CLH队列与Node节点 就像通常医院看病排队一样,医生一次能看的病人数量有限,那么超出医生看病速度之外的病人就要排队. 一条队列是队列中每一个人 ...

  9. stack的常见用法

    stack的常见用法 栈是什么? 栈是一种先进后出的容器 栈的定义 引入头文件 # include <stack> using namespace std; 定义栈 可以定义任何类型的栈 ...

  10. 洛谷 P3386 二分图匹配 题解

    题面 这道题虽然是练习匈牙利算法的,但可以用网络流来切掉它: 我们可以建立一个超级源和一个超级汇,超级源连接左部分点,超级汇连接右部分点: 然后在该图上跑最大流就可以了: PS:我设的超级源是2001 ...