【JS】DOM事件

  • 给一个孩子元素绑定了click事件,也给爸爸元素绑定了click事件,你点击了这个孩子元素,你怎么知道你到底要点击孩子仍是爸爸(由于孩子是爸爸的一部分,点击了孩子不就是点击了爸爸)
  • 因此,点击了孩子就把爸爸、爷爷、曾爷爷的点击事件一块儿触发了吧
  • 同理,孩子也有孩子,也就是孙子。你想点击了孩子,可是要是一不当心点到孙子身上,孙子由于是孩子的一部分,也算点到了孩子,就会触发孩子的事件监听函数。因此你给孩子绑定了函数,可是触发函数的多是孙子。
  • 因此,触发(target)监听函数的不必定是绑定元素,还多是绑定元素的儿子

事件

定义

  1. 事件是在编程时系统内发生的动做或者发生的事情
  2. 事件是要绑定在元素上的。好比给一个div元素绑定一个鼠标悬浮事件,给一个ol元素绑定鼠标单击事件。
  3. 可使用事件监听函数(也叫事件处理程序、侦听器)来监听事件,以便事件发生时执行相应的代码

事件类型举例(所有事件类型请看MDN文档)

  • 单击click
  • 双击dblclick
  • 鼠标放置mouseenter
  • 表单内容发生变化
  • 拖拽
  • 页面滚动
  • 触发/失去焦点
  • 键盘按下
  • 提交表单

DOM事件流

你想一想,若是我按了键盘上的空格,是否是也至关于按了整个键盘?我按了空格的右下角的英文,是否是至关于按了空格。css

定义

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

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

分为三个阶段:一、事件捕获阶段;二、当前目标阶段;三、事件冒泡阶段

事件捕获阶段(window→触发元素)

首先开始事件捕获阶段,从DOM树最根部的节点window开始,沿着DOM树向下遍历每一个元素,直到触发元素目标元素target。若是这些元素也注册了click事件(且为捕获阶段),就会执行他们相应的事件监听函数函数

事件冒泡阶段(触发元素→window)

最后是事件冒泡阶段,从触发元素目标元素target开始,向上逆着遍历DOM树,直到最根部window元素。若是这些元素也注册了click事件(且为冒泡阶段),就会执行他们相应的事件监听函数性能

例子

咱们为tr元素绑定了一个单击click事件。当咱们单击trui

若单击的是纯tr元素,即触发元素是纯tr元素

  • 绑定元素和触发元素相同
  • 事件捕获阶段:window → document → html → body → table → tbody → tr
  • 事件冒泡阶段:tr → tbody → table → body → html → document → window
  • 路径(触发元素到window,也就是冒泡阶段):tr → tbody → table → body → html → document → window

若单击的是tr元素里的td元素(也是tr元素!!!!),即触发元素是孩子

  • 绑定元素是触发元素的爸爸
  • 事件捕获阶段:window → document → html → body → table → tbody → tr → td
  • 事件冒泡阶段:td → tr → tbody → table → body → html → document → window
  • 路径(触发元素到window,也就是冒泡阶段):tr → tbody → table → body → html → document → window

如何给元素绑定事件

方法一:在html的那个元素里绑定(不要用!)

<div onclick = console.log('hi')>点我</div>this

方法二:给DOM元素的onclick属性赋值事件监听函数

$div.onclick = function(e){
    console.log('你刚才单击了这个div元素')
}
复制代码

缺点:一个元素的一种事件(如click)只能有一个事件监听函数,由于你是给这个元素的这个属性(onclick)赋值啊!下一个值会覆盖上一个值的呀。就像我若是要再给$div绑定一个click事件,再写了一个事件监听函数。这个事件监听函数仍是会成为属性onclick的新值的呀spa

方法三:调用DOM元素的addEventListener函数

优势:能够添加多个事件处理函数。代理

$div.adddEventListener(type,listener,useCapture)

  • type : 事件类型
  • listener : 事件监听函数
  • useCapture:可选,true表示在捕获阶段调用listener,false(默认)表示在冒泡阶段调用listener。

$div.adddEventListener(type,listener,options)

  • options:
  1. 可选,是个对象。
  2. {capture: 是否捕获阶段监听,once: 是否只监听一次,passive:是否忽略preventDefault }
  3. 默认全是false

移除事件处理程序target.removeEventListener(type,handler,)

经过addEventListener()添加的事件处理程序只能使用removeEventListener() 来移除;移除时传入的参数和添加程序处理程序时使用的参数相同。这也意味经过 addEventListener() 添加的匿名函数(没有传入参数)将没法移除 target.removeEventL .istener('click', handler)code

target.removeEventL .istener('click', handler, true)

例子

例子

事件对象

定义理解

var div = document.getElementById('box');
div.onclick = function(event){ };
复制代码
  1. event在这里面就是事件对象,写到事件监听函数函数的小括号() 里面,能够当作形参来看。能够本身随便命名(好比 event、e、aa)。后面用不到事件对象的话,就不须要在小括号里写。

  2. 事件对象只有有了事件才会存在,事件对象是系统自动给咱们建立的,不须要咱们传递参数(事件对象一定和事件相关,若是没有事件它就不存在,有了事件就存在了)

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

  4. 我来打印出个事件对象给大家看看,里面全是此次事件的相关信息,也就是此次事件(对象)的属性。

常见的事件对象的属性

  1. e.target:返回触发事件的元素(不必定是绑定事件的元素,如事件委托)
  2. e.type:返回事件的类型(好比click、mouseover不带on)
  3. e.preventDefault():该方法阻止默认事件(默认行为), 好比不让连接跳转
  4. e.stopPropagation():中止事件传播。在这个事件后就没了,捕获或者冒泡阶段就到此为止了。
  5. e.path:冒泡路径,从触发元素→window

注意:e.target 和 this 的区别

一、e.target 返回的是触发事件的元素;

二、this 返回的是绑定事件的元素;

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

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

有的时候,事件的绑定元素和触发元素不是同一个。

例子

  • div绑定了单击事件,那么this指向的就是dive.target 指向咱们点击的那个对象(那个元素触发的对象),点击的是div,因此e.target 指向的就是div----绑定元素和触发元素相同

  • ul绑定了单击事件,那么this指向的就是ul;e.target 指向咱们点击的那个对象(那个元素触发的对象),点击的是红框右上角,就是ul,因此e.target 指向的就是ul---绑定元素和触发元素相同

  • ul绑定了单击事件,那么this指向的就是ul;e.target 指向咱们点击的那个对象(那个元素触发的对象),点击的是li,因此e.target 指向的就是li---绑定元素和触发元素不一样

事件委托

  • 事件委托,通俗地来说,就是把一个元素响应事件(click、keydown......)的函数委托到另外一个元素;
  • 通常来说,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,当事件响应到须要绑定的元素上时,会经过事件冒泡机制从而触发它的外层元素的绑定事件上,而后在外层元素上去执行函数。
  • 事件绑定代理给父元素,由父元素根据事件来源统一处 理
  • 适用于可能会新增子元素对场景
  • 事件代理其实是事件冒泡的应用
  • 若是在须要有多个DOM事件须要监听的状况下(好比几百条微博点击事件注册),给每个DOM都绑定监听函数,对性能会有极大的影响,所以,有一解决方案为事件委托。
  • 事件委托利用了事件冒泡与event.target

委托的优势

  1. 减小内存消耗

试想一下,若果咱们有一个列表,列表之中有大量的列表项,咱们须要在点击列表项的时候响应一个事件;

<ul id="list">
  <li>item 1</li>
  <li>item 2</li>
  <li>item 3</li>
  ......
  <li>item n</li>
</ul>
// ...... 表明中间还有未知数个 li
复制代码

若是给每一个列表项一一都绑定一个函数,那对于内存消耗是很是大的,效率上须要消耗不少性能;

所以,比较好的方法就是把这个点击事件绑定到他的父层,也就是 ul 上,而后在执行事件的时候再去匹配判断目标元素;

因此事件委托能够减小大量的内存消耗,节约效率。

  1. 动态绑定事件

好比上述的例子中列表项就几个,咱们给每一个列表项都绑定了事件; 在不少时候,咱们须要经过 AJAX 或者用户操做动态的增长或者去除列表项元素,那么在每一次改变的时候都须要从新给新增的元素绑定事件,给即将删去的元素解绑事件;

若是用了事件委托就没有这种麻烦了,由于事件是绑定在父层的,和目标元素的增减是没有关系的,执行到目标元素是在真正响应执行事件函数的过程当中去匹配的;

因此使用事件在动态绑定事件的状况下是能够减小不少重复工做的。

jQuery 中的事件委托

  1. $.on: 基本用法: $('.parent').on('click', 'a', function () { console.log('click event on tag a'); }),它是.parent 元素之下的a 元素的事件代理到$('.parent') 之上,只要在这个元素上有点击事件,就会自动寻找到 .parent 元素下的 a 元素,而后响应事件;
  2. $.delegate: 基本用法: $('.parent').delegate('a', 'click', function () { console.log('click event on tag a'); }),同上,而且还有相对应的 $.delegate来删除代理的事件;
相关文章
相关标签/搜索