三言两语之js事件、事件流以及target、currentTarget、this那些事(涉及事件流)

说真的,我觉得人家写的特别好……为了防止我以后对此文修改编辑时成了“原创”,特此再把原文链接放一下

其实要讲清楚target、currentTarget,我们就不得不说一下事件流这个概念,而要言明事件流,我们也要晓得一下神马是事件以及一些周边生态概念,这三个概念是必须放在一块说,我们才能对能对这部分的知识有很好的理解。
读完本文你将可以了解如下概念:
1、神马是事件,事件三种写法html事件处理程序、dom0级、dom2级

2、事件流是什么鬼及其运用和使用上的坑~

3、target、this、currentTarget的区别

——事件

我们先聊聊事件,首先我们必须明确一点,事件通常与函数挂钩。要聊事件这个名词,我先扯下js,我们都知道js由ECMA、DOM、BOM组成,(以下这部分我虽然明白,但是感觉作者写的很好,也就一并搬过来啦)ECMA为js的基本语法,如果你实在不知道是啥,可以简单的理解为他规定了循环是用for关键字,而采用var来定义一个变量,诸如此类;BOM是浏览器对象模型的缩写,即用我们的js来操作浏览器;DOM是文档对象模型的缩写,那啥子是文档呢?简单可以这样理解——我们的html标签在被浏览器渲染的时候会生成一棵标签树,我们可以把这颗由标签构成的树别名称之为文档树或者文档,而每一个标签在js中都可以被抽成一个对象,so,到此你应该已了然于胸了吧?原来文档对象模型可以简单的理解为html标签文档在js中的对象映射,也就是有了dom这个概念,我们可以在js中操作html的元素咯(以上)。
如果把浏览器当作最顶层容器,抽象成文字可以理解为:

window-》document-》html-》head/body-》其他元素

这个层级关系就可以理解为文档树了,现在我们可以得出如下几个概念:

1.凡出现在html中的标签被浏览器解析的时候都会被挂载到dom树上。(恩,这个好说)
2.dom树上的每个标签都是一个独立的对象,既然是对象就会有属性和方法,上文也提到过事件通常与方法不离不弃,所以这里我们就会晓得一个基本常识了,事件一般会和标签和方法挂钩,嗯是的!3.我们通常在标签上注册一个事件,当事件满足条件被触发以后就会执行我们早些预定义好的方法。
事件的概念就是:让html在某些特定条件下执行了一段js脚本,某些特定的条件就是如单击,双击,鼠标经过等,这些条件以属性的形式呈现在html代码中,而触发执行的js脚本则通常为方法【这句话的话……我觉得我需要动用下我高中语文的知识,“事件”应该是个名次吧,那事件的概念这里写的好像被理解成了一个动作啊,省略来讲就是“让HTML执行脚本”,所以我觉得事件应该是“让html(在某些特定条件下)执行了(一段js)脚本”这句话里的“特定条件”,比如单击,双击】
如:
<div onclick = "fn()"></div>

<script>
funcrion fn(){
alert("我被单击了");
}
</script>
onclick为某些条件的事件句柄,fn为事件满足条件后要执行的函数,以上只是事件的一种写法,不足以应付开发,为此我们还需要了解下常见事件的几种写法:分别为最原始的html混合事件写法,dom0级写法、dom2级写法。
1.最原始的写法:和html混合在一起写,缺点是代码高冗余,且无法添加多个事件处理函数如上文对事件的举例则为典型的*html事件处理程序写法
2.dom0级:将html代码和js代码分离,且支持匿名函数,可以看到完美的改进了1的冗余缺憾,所有的事件相关操作都在js中完成
//html代码
<div id="a"></div>

//js代码
var div1 = document.getElementById("a");
a.onclick=function(){
alert("我被单击了");
}
3.dom2级:ie使用attachEventListener其他非ie使用addEventListener,可以支持绑定多个事件流

——事件流

接收顺序(事件流方式),需要我们了解:

  1. 事件捕获:从最不具体的到最具体的
  2. 事件冒泡:从最具体的到最不具体的
  3. 为什么会有两种事件流方式呢?历史原因,ie提出的是事件冒泡,而w3c提出的是事件捕获。
  4. 浏览器内部是如何解析这两种事件流的,它的执行顺序:事件捕获-》目标阶段-》事件冒泡,一句话就是先捕获后冒泡

<div id="one">
<div id="two">
<div id="three"></div>
</div>
</div>

one.addEventListener('click',function(e){
console.log('one');
},false);

two.addEventListener('click',function(e){
console.log('two');
},false);

three.addEventListener('click',function(e){
console.log('three');
},true);//就算把这里变成false,输出结果一样

false,false,true——>打印数序应该为three->two->one。
false,true ,true——>打印数序应该为two->three->one。(至于为啥的话,画几个图就明白了)

总结:现代的浏览器对事件的处理方式为先捕获后冒泡只要有事件就会按这个顺序执行,雷打不动滴,雷打不动滴。dom2级决定的只是只是只是在事件流的哪个时机去执行处理函数而已而已。
注意:当我们要绑定多个事件处理函数的时候,事件处理函数的顺序ie和非ie在默认情况下是不一致的,因为他们两个的事件流默认情况下是正好相反的,这在不指定事件流参数的情况下确实是个坑~

####(原作者铺垫了这么多就是为了以下,如果对事件流什么的都懂,那就直接看这部分好了)

  1. target:触发事件的某个具体对象,只会出现在事件流的目标阶段(谁触发谁命中,所以肯定是目标阶段)
  2. currentTarget:绑定事件的对象,恒等于this,可能出现在事件流的任意一个阶段中
  3. 通常情况下terget和currentTarget是一致的,我们只要使用terget即可,但有一种情况必须区分这三者的关系,那就是在父子嵌套的关系中,父元素绑定了事件,单击了子元素(根据事件流,在不阻止事件流的前提下他会传递至父元素,导致父元素的事件处理函数执行),这时候currentTarget指向的是父元素,因为他是绑定事件的对象,而target指向了子元素,因为他是触发事件的那个具体对象,
评论 ( 1 )
最新评论
穗穗 2017-05-17 17:37:04 1F

target:触发事件的元素(有可能不是绑定事件的元素),currentTarget:一定是绑定事件的元素(有可能不是触发事件的元素),恒等于this
PS: 文中有两处target拼错了……为了避免编辑此文就成了原创而丢了转载的原文链接,反正不是大错,就不改了……