DOM事件处理函数
事件
JavaScript与HTML之间的交互是通过事件实现的。
事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。可以使用侦听器(或是处理程序)来预定事件,以便事件发生时执行相应的代码
IE9、Firefox、Opear、Safari和Chrome全部都已经实现“DOM2级事件”模块的核心部分。
一、事件流
事件流描述的是从页面接收事件的顺序。
事件发生时元素节点之间按照特定的顺序传播,这个过程即DOM事件流。
事件流:点击了某个按钮也触发了这个按钮所在的区域,同时也触发了区域所在的页面。
DOM事件流分为三个阶段:1、捕获阶段;2、当前目标阶段;3、冒泡阶段
例如:为div注册了一个点击事件:
- 事件冒泡:IE最早提出,时间开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程;
- 事件捕获:网景Netscape Communicator 最早提出,由DOM的最顶层节点开始,然后逐级向下传播到最具体的元素的接收过程。
注意:1、JS代码中只能执行捕获或是冒泡阶段的其中一个阶段;
2、onclick 和 attachEvent 只能得到冒泡阶段;
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实体,这里使用了单引号,如果想使用双引号,可以使用(" 双引号的转义字符)
<button onclick="alert(" clicked ")">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事件处理函数的更多相关文章
- JavaScript移除绑定在元素上的匿名事件处理函数
前言: 面试的时候有点蒙,结束之后想想自己好像根本就误解了面试官的问题,因为我理解的这个问题本身就没有意义.但是当时已经有一些思路,但是在一个点上被卡住. 结束之后脑子瞬间灵光,想出了当时没有迈出的那 ...
- javascript学习笔记(四):事件处理函数和动态创建html标记。
1 HTML的事件属性 全局事件属性:HTML 4 增加了使事件在浏览器中触发动作的能力,比如当用户点击元素时启动 JavaScript. a. Window 事件属性,针对 window 对象触发 ...
- DOM事件处理有三个阶段
DOM事件处理有三个阶段: 捕捉阶段(capture phase):从最上层元素,直到最下层(你点击的那个target)元素.路过的所有节点都可以捕捉到该事件. 命中阶段(target phase): ...
- W3C和IE中的事件处理函数
在上一篇文章中提到了关于传统的JS中注册事件对象的一些缺点和问题,下面是关于DOM2级的现代事件绑定.本文中设计到的HTML文件在文章最后 一.W3C事件处理函数 “DOM2 级事件”定义了两个方法, ...
- js中关于事件处理函数名后面是否带括号的问题
今天总结一个关于事件处理程序的小细节.首先回顾一下事件处理的一些概念. JS中的事件处理(事件绑定)就是让某种或某些事件触发某些活动.有两种常见的形式,分别是DOM Level 0 和DOM Leve ...
- 前端魔法堂:onsubmit和submit事件处理函数怎么不生效呢?
前言 最近在用Polymer增强form,使其支持表单的异步提交,但发现明明订阅了onsubmit和submit事件,却怎么也触发不了.下面我们将一一道来. 提交表单的方式 表单仅含一个以下的元素时 ...
- jQuery总结--版本二 事件处理函数
一:事件处理函数 (1) one(事件名称, fn) 仅对指定事件监听一次,监听事件只会执行一次 <!DOCTYPE html> <html> <head lang=&q ...
- 前端菜鸟学习之DOM事件处理
一.事件处理程序 1.DOM0级事件处理程序:就是将一个函数赋值给一个事件处理程序属性,至今仍为现代所有浏览器所支持,主要得益于其跨浏览器的优势,要使用DOM0级事件 首先要得到操作对象的引用,具体实 ...
- React 学习(三) ---- state 和 事件处理函数
在上两节中,我们讲述了props, 组件使用props进行渲染,但是这是一次性的, props渲染完成之后就不做任何事情了,但是现实中却不是这样的,当我们点击购物车上的加减按钮时,数量会自动加1或减1 ...
随机推荐
- #Java学习之路——基础阶段二(第十二篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- 在windows上远程访问服务器jupyter notebook
需求: 之前在服务器上只能运行完整的python文件,而不能实现jupyter notebook的交互模式,通过在本地浏览器上远程访问服务器上的jupyter notebook,这样不就能有一个很棒的 ...
- Python_Onlineh_Hmework(基础篇,持续更新中...)
1 递归 1.1 定义一个函数,求一个数的阶乘 def func(x): if x == 2: return 2 else: return x*func(x-1) a = func(4) print( ...
- HTML标签-->列表,表格
只有努力奔跑,才能一直停留在原地. 无序列表 <ul><!--默认列表编号为(实心圆)--> <li>第一项</li> <li>第二项< ...
- Linux系统搭建并管理Git服务器
搭建Git服务器 GitHub就是一个免费托管开源代码的远程仓库.但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护费,那就只能自己搭建一台Git服务器作为私有仓 ...
- tableau日常管理
各文件位置: https://help.tableau.com/current/server-linux/zh-cn/cli_default_filepaths_tsm.htm ldap配置: htt ...
- python 科学计数法转数值
猜测python应该是有现成的模块可以解决该问题,不过没找到,所以自己简单写了个函数处理: def tranform(inputString): num_value = re.compile('^[0 ...
- Tomcat配置:java.lang.UnsatisfiedLinkError: D:\DevelopTool\tool20150402\tomcat\apache-tomcat-8.5.16\bin\tcnative-1.dll: Can't load AMD 64-bit .dll on a IA 32-bit platform
解决办法: tomcat启动时提示java.lang.UnsatisfiedLinkError: D:\soft\devTool\apache-tomcat-7.0.57\bin\tcnative-1 ...
- 区间和序列上的dp
区间上的dp状态设计最基本的形式: \(F[i]\)表示以i结尾的最优值或方案数. \(F[i][k]\)表示以i结尾附加信息为k的最优值或方案数. 当然可以有多维附加信息. 转移的话往往是枚举上一个 ...
- AppCan适配问题
使用AppCan调试中心时,屏幕适配是个问题,经过多次调试总结出如下经验: 1,使用HD+(1560 x 720):显示错乱 2,使用FHD+ (2340 x 1080):显示错乱 3,HD (128 ...