javaScirpt事件详解-原生事件基础(一)

 

事件

JavaScript与HTML之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间,通过监听特定事件的发生,你能响应相关的操作。图片引用:UI Events

事件流

主要是当时的IE团队提出的事件流逝是事件冒泡流,而Netscape提出的是事件捕获流, 可以使用DOM2级定义的addEventListener()方法来处理在冒泡或者捕获阶段调用事件处理程序。

事件冒泡

即事件开始时由最具体的元素(文档中嵌套最深的节点)接收,然后逐级向上传播到较为不具体的节点。

事件捕获

即最外层的元素更早接收到事件,而最具体的元素应该最后接收到事件。事件捕获的用意在于在事件到达预定目标之前捕获它。

DOM事件流

而“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段,处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,然后是实际的目标接收到事件,最后一个阶段是冒泡阶段。

addEventListener函数接收三个参数,要处理的事件名、作为事件处理程序的函数和一个布尔值,最后的布尔值如果是true,表示在不回阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。

事件捕获:

//html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div class="a">
<div class="b">
<button class="c">click</button>
</div>
</div>
</body>
</html> var $body = document.querySelector("body"),
$a = document.querySelector(".a"),
$b = document.querySelector(".b"),
$c = document.querySelector(".c"); $body.addEventListener("click",function(){
console.log(this);
},true);
$a.addEventListener("click",function(){
console.log(this);
},true);
$b.addEventListener("click",function(){
console.log(this);
},true);
$c.addEventListener("click",function(){
console.log(this);
},true);

单击button,则

事件冒泡:

$body.addEventListener("click",function(){
console.log(this);
},false);
$a.addEventListener("click",function(){
console.log(this);
},false);
$b.addEventListener("click",function(){
console.log(this);
},false);
$c.addEventListener("click",function(){
console.log(this);
},false);

单击button,则

上述代码在IE9和其他现代浏览器都支持(测试页)。IE8及更早版本不支持DOM事件流只有事件冒泡。所以我们有两个阶段可以在目标对象上操作事件,但为了兼容性考虑,一般用冒泡的情况比较多。

事件处理程序

事件是用户或浏览器自身执行的某种动作,而响应某个事件的函数就叫做事件处理程序(或事件侦听器)

HTML事件处理程序

即内联式处理函数,以"on"开头:

<button onclick="alert(this)"></button>

虽然方便,但有很大问题,首先,存在时差问题,因为用户可能会在HTML元素一出现在页面上就触发相应的事件,但当时的事件处理程序有可能尚不具备执行条件;另一个缺点是:这样扩展事件处理程序的作用域链在不同浏览器会导致不同结果;而最后的缺点则是HTML与JavaScript代码紧密耦合,如果要更换事件处理程序,就要改动两个地方。

DOM0级事件处理程序

通过JavaScript指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。 每个元素(包括window和docuemnt)都有自己的事件处理程序属性,这些属性通常全部小写:

var btn = document.getElementById('myBtn');
btn.onclick = function(){
alert("Clicked");
}

以这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。

DOM2级事件处理程序

“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()和removeEventListener()。所有DOM节点中都包含这两个方法,在上面的事件捕获和冒泡有用到。使用DOM2级方法添加事件处理程序的主要好处是可以添加多个事件处理程序。

IE事件处理程序

IE实现的方法是:attachEvent()和detachEvent()。这两个方法接收相同的两个参数:事件处理程序名称与事件处理程序函数。通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段:

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
alert("Clicked");
})

这里的参数中表行为的是onclick而非DOM的addEventListener()方法中的click,在IE中使用attachEvent()与使用DOM0级方法的主要区别在于事件处理程序的作用域,在使用DOM0级方法的情况下,事件处理程序会在其所属元素的作用域内运行;在使用attachEvent()方法的情况下,事件处理程序会在全局作用域中运行,因此this等于window

var btn = document.getElementById("myBtn");
btn.attachEvent('onclick',function(){
alert(this === window);// true
});

事件对象

在触发DOM上的某个事件时,会产生一个事件对象event,所有浏览器都支持event对象,但支持方式不同。

DOM中的事件对象

event对象包含与创建它的特定事件有关的属性和方法。触发的事件类型不一样,可用的属性和方法也不一样。不过,所有事件都有下表的成员属性。

属性/方法 类型 读/写 说明
bubbles boolean 只读 表明事件是否冒泡
cancelable boolean 只读 表明是否可以取消事件的默认行为
currentTarget element 只读 其事件处理程序当前正在处理事件的那个元素
defaultPrevented boolean 只读 为true表示已经调用了preventDefault()DOM3新增
datail integer 只读 与事件相关的细节信息
eventPhase integer 只读 调用事件处理程序的阶段:1表示捕获阶段,2表示处于目标 3表示冒泡阶段
preventDefault() function 只读 取消事件的默认行为。如果cancelable是true,则可以使用这个方法
stopImmediatePropagation() function 只读 取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用(DOM3级新增)
stopPropagation() function 只读 取消事件的进一步捕获或冒泡,如果bubbles为true,则可以使用这个方法
target element 只读 事件的目标
isTrusted boolean 只读 返回一个布尔值,表明当前事件是否是由用户行为触发,还是由一个脚本生成的
type string 只读 被触发的事件的类型
view AbstractView 只读 与事件关联的抽象视图。等同于发生事件的window对象

更详细的文档可以看 这里

在事件处理程序内部,对象this始终等于currentTarget的值,而target则只包含事件的实际目标。如果直接将事件处理程序指定给了目标元素,则this,currentTarget和target包含相同的值。

根据event所拥有的属性,就可以更加细致的操作事件。在w3c的这篇Events中,我们可以知道哪些事件可以冒泡. 首先是冒泡事件,如果只需要在具体节点触发,而不冒泡到包裹层中,则可以使用与冒泡行为相关的一系列属性,举例:

<div class="a">
<a href="http://www.cnblogs.com"></a>
</div>

在这个div中,如果div和a都有监听点击事件,那么在点击a标签的时候(默认事件流在已过捕获阶段),会先触发a的点击事件,然后是div的点击事件,最后是a标签的默认事件。如果不想冒泡,也就是说点击a时只触发a的点击事件,则可以使用stopPropagation()方法:

var $a = document.querySelector("a");
$a.addEventListener("click",function(event){
if(event.bubbles){
event.stopPropagation();
}
});

也可以在处理程序里直接删除节点,也能阻止冒泡。 当然,有时我们不希望跳转页面,而是执行自定义的脚本,那就可以使用preventDefault()方法:

var $a = document.querySelector("a");
$a.addEventListener("click",function(event){
if(event.bubbles){
event.preventDefault();
// do something
}
});

有时我们可能会接手他人的代码,在不了解具体代码的情况下,如果只是单个独立事件需要修改,则可以在运行老的js代码之前,使用stopPropagation()方法。

$a.addEventListener('click',function(event){
event.preventDefault();
event.stopImmediatePropagation();
// do something
}) $a.addEventListener("click",function(event){
alert("这是a标签");
});

当然,冒泡并不是说是一件坏事,因为场景很多变,在某些场景下,冒泡也是很有用的,比如说事件代理(delegation)。 有时我们需要对生成的节点附加操作,event总是需要先找到element,再进行注册,才可以进行事件监听,那么对于这些生成的节点来说,当然可以在生成之后再次对该节点重新注册事件。但如果是生成了同一个标记的节点呢? 那么我们不仅需要把之前注册的事件remove,还需要重新绑定之前的标记,否则会二次触发。这时候事件代理 就可以解决这一类问题。根据DOM事件流,我们可以知道,在节点冒泡时,可以一直往上冒泡,所以,我们完全可以把事件代理给点击节点的父节点来做,根据event.target属性,我们可以知道指向触发事件的对象到底是谁,也因此,不用再使用繁琐的重新注册事件,就可以直接操作子元素。像jQuery,Zepto中都有关于事件代理的处理方法,后篇会继续涉及到。

$div.addEventListener("click",function(event){
alert("这是外层");
if(event.target) {
event.target.style.visibility = 'hidden';
}
});

冒泡也会有副作用,mouseout事件会导致离开内部节点时提前触发,为此,jQuery自定义了mouseenter和mouseleave事件,Zepto也有相应的事件。 只有在事件处理程序执行期间,event对象才会存在;一旦事件处理程序执行完成,event对象就会被销毁(闭包)

IE中的事件对象

在IE中访问event,特别是IE6~8尤其注意,在使用DOM0级方法添加事件处理程序时,event对象作为window对象的一个属性存在。

var btn = document.getElementById('a');
btn.onclick = function(){
var event = window.event;
alert(event.type); //"click"
}

而IE中的event对象都会包含下表的属性和方法:

属性/方法 类型 读/写 说明
cancelBubble Boolean 读/写 默认值为false,但将其设置为true就可以取消事件冒泡(与DOM中的stopPropagation()方法的作用相同)
returnValue Boolean 读/写 默认值为false,但将其设置为false就可以取消事件的默认行为(与DOM中的preventDefault()方法的作用相同)
srcElement Element 只读 事件的目标(与DOM中的target属性相同)
type String 只读 被触发的事件的类型

事件类型

不表

事件模拟

结合jQuery和Zepto源码总结。

部分用例:event

长路漫漫,与君共勉

如果您看完本篇文章感觉不错,请点击一下右下角的推荐来支持一下博主,谢谢!
 
分类: javaScript
标签: javascript
---------------------->此文转载!

JAVASCRIPT事件详解-------原生事件基础....的更多相关文章

  1. javaScirpt事件详解-原生事件基础(一)

    事件 JavaScript与HTML之间的交互是通过事件实现的.事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间,通过监听特定事件的发生,你能响应相关的操作.图片引用:UI Events 事件流 ...

  2. Android事件详解——拖放事件DragEvent

    1.Android拖放框架的作用? 利用Android的拖放框架,可以让用户用拖放手势把一个View中的数据移到当前layout内的另一个View中去. 2.拖放框架的内容? 1)拖放事件类 2)拖放 ...

  3. JavaScript事件详解-Zepto的事件实现(二)【新增fastclick阅读笔记】

    正文 作者打字速度实在不咋地,源码部分就用图片代替了,都是截图,本文讲解的Zepto版本是1.2.0,在该版本中的event模块与1.1.6基本一致.此文的fastclick理解上在看过博客园各个大神 ...

  4. JavaScript事件详解-zepto的事件实现

    zepto的event 可以结合上一篇JavaScript事件详解-原生事件基础(一)综合考虑源码暂且不表,github里还有中文网站都能下到最新版的zepto.整个event模块不长,274行,我们 ...

  5. DOM——事件详解

    事件 事件:触发-响应机制 事件三要素 事件源:触发(被)事件的元素 事件名称: click 点击事件 事件处理程序:事件触发后要执行的代码(函数形式) 事件的基本使用  var box = docu ...

  6. JavaScript事件详解-jQuery的事件实现(三)

    正文 本文所涉及到的jQuery版本是3.1.1,可以在压缩包中找到event模块.该篇算是阅读笔记,jQuery代码太长.... Dean Edward的addEvent.js 相对于zepto的e ...

  7. JavaScript中的鼠标滚轮事件详解

    JavaScript中的鼠标滚轮事件详解/*Firefox注册事件*/ ~~~Firefox: addEventListener('DOMMouseScroll', handler, false)if ...

  8. react第五单元(事件系统-原生事件-react中的合成事件-详解事件的冒泡和捕获机制)

    第五单元(事件系统-原生事件-react中的合成事件-详解事件的冒泡和捕获机制) 课程目标 深入理解和掌握事件的冒泡及捕获机制 理解react中的合成事件的本质 在react组件中合理的使用原生事件 ...

  9. 第三天:JS事件详解-事件流

    学习来源: F:\新建文件夹 (2)\HTML5开发\HTML5开发\04.JavaScript基础\6.JavaScript事件详解 学习内容:  1)基础概念 2)举例说明: 代码如上,如果用事件 ...

随机推荐

  1. Asp.net mvc5 解析route源码实现自己的route系统

    url route 路由系统的责任是找到匹配的路由,创建路由数据,并将请求分配给一个处理程序. 选择动作是 MVC 的处理程序的实现细节.它使用路由数据和从传入请求其他信息来选择要执行的操作 实例 源 ...

  2. 在chrome浏览器和在IE浏览器中显示的页面样式不一样的解决办法

    在IE浏览器中添加 一行代码即可:<meta http-equiv="X-UA-Compatible" content="IE=edge" /> 位 ...

  3. 八大排序算法之三选择排序—简单选择排序(Simple Selection Sort)

    基本思想: 在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换:然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素 ...

  4. Python下科学计算包numpy和SciPy的安装

    转载自:http://blog.sina.com.cn/s/blog_62dfdc740101aoo6.html Python下大多数工具包的安装都很简单,只需要执行 “python setup.py ...

  5. SQL-字符串合并

    create table tb(id int, value varchar(10))  insert into tb values(1, 'aa')  insert into tb values(1, ...

  6. Radar Installation 分类: POJ 2015-06-15 19:54 8人阅读 评论(0) 收藏

    Radar Installation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 60120   Accepted: 13 ...

  7. Unity-Animator深入系列---Foot IK

    回到 Animator深入系列总目录 最近在做一个demo,遇到了角色跑动不自然的问题(注意双腿): 后来得知勾选FootIK之后Unity会智能修复这类问题: 好像这个功能还能做到斜面地形匹配,不过 ...

  8. PHP比较运算!=和!==

    PHP!=和!==的区别 !==是指绝对不等于,比如,$a = 3, $b="3" 那么,$a!==$b成立,可是$a!=$b不成立:

  9. Android mvp模式、mvvm模式

    MVC和MVP的区别2007年08月08日 星期三 上午 09:23 MVC和MVP到底有什么区别呢? 从这幅图可以看到,我们可以看到在MVC里,View是可以直接访问Model的!从而,View里会 ...

  10. ContentProvider官方教程(4)ContentResolver权限

    Content Provider Permissions A provider's application can specify permissions that other application ...