DOM事件理解

概述

DOM的事件操作(监听和触发)都定义在EventTarget接口。所有节点对象都部署了这个接口,其他一些需要事件通信
的浏览器内置对象也部署了这个接口,比如XMLHttpRequestAudioNodeAudioContext)。
该接口主要提供三个实例方法:

  • addEventListener:绑定事件的监听函数
  • removeEventListener:移除事件的监听函数
  • dispatchEvent:触发事件

DOM事件级别分类

DOM0级、DOM2级、DOM3级事件。

DOM0级事件

2步:
1、先找到DOM节点
2、把处理函数赋值给该节点对象的事件属性
eg:

<div id="box"></div>
<script>   
    var box = document.getElementById('box')
    box.onclick = function () {
        console.log("1")	
    } 
 </script>

解除事件:把null赋值给事件属性。document.getElementById('box').onclick = null;
缺点: 无法给一个对象添加多个事件处理函数。

DOM2级事件

1、EventTarget.addEventListener():用于在当前节点或对象上,定义一个特定事件的监听函数。一旦这个事件发生,就会执行监听函数。该方法没有返回值。
target.addEventListener(type, listener[, useCapture]);

2、使用addEventListener:

<div id="box"></div>
<script>   
    var box = document.getElementById('box')
    function greet() {
        console.log('Hello World');
    }
    box.addEventListener('click', greet, false)
 </script>

addEventListener参数含义:
第一个参数type: 事件名称,即:事件属性去掉on,大小写敏感
第二个参数listener:事件处理函数/监听函数,事件发生时,会调用该监听函数
第三个参数useCapture:布尔值,表示监听函数是否在捕获阶段触发,默认是false(监听函数只在冒泡阶段被触发)。

此外,第二个参数除了监听函数,还可以是一个具有handleEvent方法的对象:

box.addEventListener('click', {
	handleEvent: function (event) {
		console.log('click')
	}
})

第三个参数除了布尔值useCapture,还可以是一个属性配置对象,该对象的具体属性如下:

  • capture: 布尔值, 表示该事件是否在捕获阶段触发监听函数
  • once: 布尔值,表示监听函数是否只触发一次,然后就自动移除
  • passive: 布尔值,表示监听函数不会调用事件的preventDefault方法,如果监听函数调用了,浏览器将忽略这个要求,并在监控台输出一行警告。

比如:

box.addEventListener('click', function (event) {
	// 只执行一次的代码
}, {once: true})

3、 优点:可以随意添加多个处理函数。注意,执行顺序与添加顺序相关,即先添加先触发。如果为同一个事件多次添加同一个监听函数,该函数只会执行一次,多余的添加将自动被去除(不必使用removeEventListener方法手动去除)。

function hello() {
  console.log('Hello');
}

document.addEventListener('click', hello, false);
document.addEventListener('click', hello, false);

执行上面代码,点击文档只会输出一行Hello。

4、如果希望向监听函数传递参数,可以用匿名函数包装一下监听函数,下面代码通过匿名函数,向监听函数print传递了一个参数:

function print(x) {
  console.log(x);
}

var el = document.getElementById('div1');
el.addEventListener('click', function () { print('Hello'); }, false);

5、监听函数内部的this,指向当前事件所在的那个对象,下面代码中,监听函数内部的this指向事件所在的对象dvBox

// HTML 代码:
// <div id="dvBox">
// 	 <p></p>
// </div>
var dvBox = document.getElementById('dvBox')
dvBox.addEventListener('click', function (e) {
  console.log(this.nodeName); 
}, false);

6、 EventTarget.removeEventListener()
用来移除addEventListener方法添加的事件监听函数,该方法没有返回值。
addEventListener方法完全一致,且removeEventListener方法移除的监听函数,必须是addEventListener方法添加的那个监听函数,而且必须在同一个元素节点,否则无效。
7、EventTarget.dispatchEvent()
该方法在当前节点上触发指定事件,从而触发监听函数的执行。该方法返回一个布尔值,只要有一个监听函数调用了Event.preventDefault(),则返回值为false,否则为true

target.dispatchEvent(event)  // 参数是一个Event对象的实例
box.addEventListener('click', hello, false);
var event = new Event('click');
box.dispatchEvent(event);

上面代码在当前节点触发了click事件

根据dispatchEvent方法的返回值,判断事件是否被取消了:

var canceled = !cb.dispatchEvent(event);
if (canceled) {
  console.log('事件取消');
} else {
  console.log('事件未取消');
}

注意:IE8及一下,需要使用attachEventdetachEvent来添加和移除事件,它们只包含两个参数,第一个是事件属性(包含on),第二个是处理函数,不支持事件捕获所以没有第三个参数。因为IE8以及更早的浏览器版本只支持事件冒泡。

DOM3级事件

在DOM2基础上增加了更多的事件类型

  • UI事件,当用户与页面上的元素交互时触发,如:load、scroll
  • 焦点事件,当元素获得或失去焦点时触发,如:blur、focus
  • 鼠标事件,当用户通过鼠标在页面执行操作时触发如:dbclick、mouseup
  • 滚轮事件,当使用鼠标滚轮或类似设备时触发,如:mousewheel
  • 文本事件,当在文档中输入文本时触发,如:textInput
  • 键盘事件,当用户通过键盘在页面上执行操作时触发,如:keydown、keypress
  • 合成事件,当为IME(输入法编辑器)输入字符时触发,如:compositionstart
  • 变动事件,当底层DOM结构发生变化时触发,如:DOMsubtreeModified

事件冒泡与事件捕获

首先看一个结构:

<html>
    <body>
        <div>
            <span>
                目标内容
            </span>
        </div>
    </body>
</html>

给最里面的目标内容绑定事件,就会有一个事件源和目标之间的事件流,此例中,事件流的方向为window -> document -> html -> body -> div -> span -> 目标 -> span -> div -> body -> html -> document -> window,整个事件流分为两个部分,以事件目标为界限,从window到目标这个过程为事件捕获,从目标回到window的过程叫事件冒泡
事件流
事件默认的处理阶段为冒泡阶段。实际开发中,经常会利用到事件冒泡,也经常需要阻止事件冒泡,这就涉及到事件对象event的相关内置方法和属性。

注意:

  • 不是所有的事件都能冒泡,如:blur、focus、load、unload都不能
  • 不同的浏览器,阻止冒泡的方式也不一样,在w3c标准中,通过event.stopPropagation()完成, 在IE中则是通过自身的event.cancelBubble=true来完成。

event事件对象

事件处理函数会回调一个参数event,代表当前事件对象,event中有很多常用的方法和属性:

  • preventDefault 阻止默认行为,比如当点击submit按钮时候,可以采用此方法阻止表单提交。
  • stopPropagation 停止事件冒泡,需要防止事件冒泡带来的负面影响的时候就要使用该方法。
  • stopImmediatePropagation 阻止后续事件,该方法除了阻止事件冒泡外在当前事件被绑定多个处理程序的时候,后续的处理程序也会被阻止。
  • currentTarget 此属性返回当前事件所绑定的对象。
  • target 此属性返回当前触发事件的对象,注意target是触发事件的对象,是真正的事件源,同样以上面的HTML为例,给div绑定一个事件,点击带文字的span后,target是span,而currentTarget是div。

为什么target是span,而currentTarget是div?
因为默认情况下的事件处理阶段是事件冒泡阶段,点击span会冒泡到div去触发div上绑定的事件,所以span是真正的事件源,是触发事件的对象,而div是当前绑定该事件的对象。

应用:利用事件冒泡实现事件委托:

<ul id="fruit">
    <li>苹果</li>
    <li>香蕉</li>
    <li>西瓜</li>
    <li>草莓</li>
  </ul>

如果想要实现点击每个li标签就能打印出文本内容,只需要利用事件冒泡即可:

 var fruit= document.getElementById('fruit');
 function log(e) {
   console.log(e.target.innerText);
 }
 fruit.addEventListener('click', log, false);

event.preventDefault() 阻止默认事件的理解: 这里的默认事件指的是HTML标签的默认事件,与JavaScript没有关系, 比如a标签,点击的时候就是默认打开href属性对应的链接,会阻止默认事件但是依然会发生事件冒泡。

事件委托

什么是事件委托? — 将元素的事件委托给它的父级或者更外级元素处理。
适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress
不适合事件委托的:mouseovermouseout虽然也有事件冒泡,但是处理它们的时候需要特别的注意,因为需要经常计算它们的位置,处理起来不太容易。此外,focusblur之类的,本身就没用冒泡的特性,自然就不能用事件委托了。

参考链接:
EventTarget 接口

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值