Javascript中的DOM(三) 事件与Event对象

事件

浏览器事件是DOM 中发生的任何事件,如网页完成加载,输入字段被修改,按钮被点击等等,事件可以被JavaScript 侦测到。

如果我们给可能发生的事件注册一个处理方法,即:如果发生了就怎样怎样,那么这个应对就是事件处理函数。一旦事件发生,在事件处理函数中可以获取到一个Event对象,其中包含着事件的信息,如事件的类型、触发此事件的元素(事件源对象)、事件发生的时间等等。

下面的例子中页面上有个按钮(id为btn),给这个按钮注册了click事件的事件处理函数,一旦按钮被点击,就会执行事件处理函数,而在事件处理函数中,能够获取到event对象。

document.getElementById('btn').addEventListener('click',function (event) {
  console.log(event);
})

在这里插入图片描述
通过上图可以发现event是一个MouseEvent对象,在它的原型链上能找到UIEvent和Event。
PS:event对象只在事件发生的过程中有效,为了兼容所有浏览器,如果需要event对象,最好将event作为形参传入。

事件的种类

支持哪些事件是宿主环境决定的,不同的浏览器支持的事件可能不同,未来浏览器可能还会支持更多的事件,同时我们也可以自己定义事件。
按照事件的触发方式常用的有:

鼠标事件

在Element对象上触发

事件说明
mousedown鼠标的键钮被按下。
mouseup鼠标的键钮释放弹起。
click鼠标左键(或中键)被单击,事件触发顺序是:mousedown -> mouseup -> click
dblclick鼠标左键(或中键)被双击。事件触发顺序是:mousedown -> mouseup -> click -> mousedown -> mouseup -> click -> dblclick。
contextmenu弹出右键菜单,它可能是鼠标右键触发的,也可能是键盘的菜单键触发的。
mouseover鼠标移动到目标上方。
mouseout鼠标从目标上方移出。
mousemove鼠标在目标上方移动

键盘事件

在Document、Element上触发

事件说明
keydown在键盘上按下某个键时触发
keypress按下某个键盘键并释放时触发
keyup释放某个键盘键时触发,该事件仅在松开键盘时触发一次

表单事件

在HTMLFormElement上触发

事件说明
reset点击表单重置按钮时触发
submit点击表单提交按钮时触发

视图事件

事件说明
fullscreenchange (en-US)An element was turned to fullscreen mode or back to normal mode.
fullscreenerror (en-US)It was impossible to switch to fullscreen mode for technical reasons or because the permission was denied.
resize (en-US)The document view has been resized.
scroll (en-US)The document view or an element has been scrolled.

拖放事件

事件说明
drag正在拖动元素或文本选区(在此过程中持续触发,每 350ms 触发一次)
dragend拖放操作结束。(松开鼠标按钮或按下 Esc 键)
dragenter被拖动的元素或文本选区移入有效释放目标区
dragstart用户开始拖动HTML元素或选中的文本
dragleave被拖动的元素或文本选区移出有效释放目标区
dragover被拖动的元素或文本选区正在有效释放目标上被拖动 (在此过程中持续触发,每350ms触发一次)
drop元素在有效释放目标区上释放

资源事件

即网页的加载与卸载等相关的事件,在window,document上触发

事件说明
error资源加载失败时。
abort正在加载资源已经被中止时。
load资源及其相关资源已完成加载。
beforeunloadwindow,document 及其资源即将被卸载。
unload文档或一个依赖资源正在被卸载。

更多事件类型

Event 对象

Event 对象代表事件的状态,只在事件发生的过程中才有效,其中包含着事件发生时的信息如其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态等等。

Event对象的属性和方法

标准 Event 属性

不同的浏览器中event对象的属性不尽相同,这里只记录一些标准 的Event 属性

属性描述
type事件名称
bubbles事件是否是起泡事件类型。
cancelable是否可拥可取消的默认动作。
currentTarget触发该事件的元素。
eventPhase事件传播的当前阶段
target返回触发此事件的元素(事件的目标节点)。
timeStamp返回事件生成的日期和时间
button哪个鼠标按钮被点击。
relatedTarget返回与事件的目标节点相关的节点

常用方法

  • initEvent() 初始化新创建的 Event 对象的属性。
  • preventDefault() 通知浏览器不要执行与事件关联的默认动作(阻止默认动作)。
  • stopPropagation() 阻断事件流

Event的继承类

基于Event 类,DOM中还定义了一些事件的继承类,如常见的:
MouseEvent,KeyboardEvent,FocusEvent,TouchEvent…

MouseEvent对象

通过给鼠标事件绑定处理函数,可以得到一个MouseEvent对象

MouseEvent对象的属性
属性描述
button鼠标的哪一个键触发的事件,0 鼠标左键, 1 鼠标中键, 2 鼠标右键
altKey“ALT” 是否被按下。
shiftKey“SHIFT” 键是否被按下
ctrlKey“CTRL” 键是否被按下
metaKey“meta” 键是否被按下
clientX鼠标相对于浏览器视口的水平位置
clientY鼠标相对于浏览器视口的垂直位置
screenX鼠标相对于用户屏幕的水平位置
screenY鼠标相对于用户屏幕的垂直位置
pageXclientX + 横向滚动距离
pageYclientY + 纵向滚动距离
xclientX的别名
yclientY的别名

图解Js event对象offsetX, clientX, pageX, screenX, layerX, x区别

KeyboardEvent对象

通过给键盘事件绑定处理函数,可以得到一个KeyboardEvent对象

KeyboardEvent的常用属性
属性说明
keyCode该属性包含键盘中对应键位的键值
charCode该属性包含键盘中对应键位的 Unicode 编码,仅 DOM 支持
target发生事件的节点(包含元素),仅 DOM 支持
srcElement发生事件的元素,仅 IE 支持
shiftKey是否按下 Shift 键,如果按下返回 true,否则为false
ctrlKey是否按下 Ctrl 键,如果按下返回 true,否则为false
altKey是否按下 Alt 键,如果按下返回 true,否则为false
metaKey是否按下 Mtea 键,如果按下返回 true,否则为false,仅 DOM 支持

关于继承类以及Event 对象的属性与方法,详见:https://developer.mozilla.org/zh-CN/docs/Web/API/Event

DOM事件流

DOM事件流指从页面中接收事件的顺序,也可理解为事件在页面中传播的顺序。

传播顺序有两种类型:事件捕捉和事件冒泡。

  • 冒泡型事件:事件由叶子节点沿祖先节点一直向上传递直到根节点。
  • 捕获型事件:与冒泡型刚好相反,由DOM树最顶层元素一直到最精确的元素。

PS:早期的IE事件流是冒泡, 从里面往上面冒, 网景是从外部元素往内部元素捕获;w3c 采用折中的方式,制定了统一的标准——先捕获再冒泡。

DOM2规定事件流包括三个阶段,事件捕获阶段,处于目标阶段,事件冒泡阶段,首先发生的是事件捕获,为截取事件提供机会,然后是实际目标接收事件,最后是冒泡阶段,在所有的现代浏览器都实现了DOM2标准事件流。

在下图中,以body节点为例,假设点击了div元素,标准事件流将2次经过body节点:一次是捕获阶段3,一次是冒泡阶段5,这两个阶段都可以绑定事件处理函数,通常我们在冒泡阶段绑定函数。

在这里插入图片描述

<a href="#" id="test">链接</a>
<script type="text/javascript">
  var test = document.getElementById('test');
  test.addEventListener('click', function () {
    console.log(this.tagName+'捕获阶段')
  }, true);
  test.addEventListener('click', function () {
    console.log(this.tagName+'冒泡阶段')
  }, false);
  document.body.addEventListener('click', function () {
    console.log(this.tagName+'捕获阶段')
  }, true);
  document.body.addEventListener('click', function () {
    console.log(this.tagName+'冒泡阶段')
  },false);
</script>

上例中用addEventListener函数为元素注册事件监听器,参考后面的事件监听 。
在这里插入图片描述

阻止冒泡和捕获,取消默认行为

阻止冒泡和捕获的目的就是阻断事件流的传播。
在html代码中,有些元素拥有自己的默认行为,如submit按钮,单击后会自动提交表单元素,如超级链接标签,单击后会自动跳转到指定的页面。

  • event.stopPropagation()方法,既可以阻止事件冒泡,但是会发生默认事件。
  • event.preventDefault()方法,取消事件的默认动作,但会发生事件冒泡 。
    这个方法通知浏览器取消执行与事件关联的默认动作。如<a>标签的地址跳转等。
  • return false方法,不但可以阻断事件流,还可以取消默认行为,并且会跳出处理函数,return false之后的所有事件都不会执行。

在前面的例子中,<a>标签有默认动作,事件冒泡后,会发生默认事件,你会看到地址栏中多了一个#,通过下面的代码可以测试一下

test.addEventListener('click', function () {
  console.log(this.tagName+'冒泡阶段');
  event.stopPropagation();  //阻止事件冒泡
  //event.preventDefault();   //取消事件的默认动作
  //return false;    //会跳出处理函数,return false之后的所有事件都不会执行
}, false);

注册事件监听器

要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数。
DOM中的事件分为DOM0级事件,DOM2级事件,DOM3级事件。

  • DOM0级事件是可以通过给元素对象的属性赋值的方式,绑定事件处理函数,如onclick,onkeyup,onfocus,onchange等属性,浏览器会把一些常用事件挂载到元素对象的私有属性上,让我们可以实现DOM0事件绑定。
  • DOM2级是通过 addEventListener 绑定的事件
  • DOM3级事件在DOM2级事件的基础上添加了更多的事件类型,也允许使用者自定义一些事件。

有三种方式可以为DOM元素注册事件处理函数。

一、普通绑定

普通绑定是DOM0级事件处理方式,浏览器会把一些常用事件挂载到元素对象的私有属性上,让我们可以实现DOM0事件绑定。
如:element.οnclick=function(){}, 注意 onclick是属性不是事件,click才是事件

原理

给当前元素的某一私有属性(onXXX)赋值的过程,赋的值是一个函数。如果赋值成功浏览器会把DOM元素和赋值的函数建立关联,建立DOM元素的行为监听,当事件被触发,浏览器会把赋值的函数执行;
只有DOM元素天生拥有这个私有属性(onxxx事件私有属性),我们赋值的方法才叫事件绑定,否则属于设置自定义属性;

  • 绑定的方法都是在冒泡传播阶段执行
  • 在DOM0事件绑定中,只能给当前元素的某一事件行为绑定唯一一个方法,若绑定多个方法,最后一次的绑定的会替换前面的绑定。
  • 移除事件绑定的时候,我们只需要给属性赋值为null;

有两种方法实现DOM0级事件绑定
1、在DOM元素中直接绑定;
2、在JavaScript代码中绑定;
下面的代码中,给两个按钮用不同的方法都绑定了事件处理函数hello

<button onclick="hello()">按钮1</button>
<button id="btn">按钮2</button>
<script type="text/javascript">
  var btn=document.getElementById('btn');
  var hello=function(){
    console.log(event.target.innerText+'被点击了');
    console.log(this);
    console.log(event);
  };
  btn.onclick=hello;
</script>

在这里插入图片描述
代码执行时,发现方法1的this指向window,方法2的this指向this指定当前元素btn

二、事件监听

用 addEventListener()来绑定事件监听函数。

原理

所有的Node对象都部署了EventTarget接口(可以接收事件的对象实现的接口),addEventListener是在其原型上定义的,调用时,浏览器会给当前元素的某个事件行为开辟一个事件池(事件队列),当我们通过 addEventListener进行事件绑定的时候,会把绑定的方法放在事件池中;
在这里插入图片描述

当元素的某一行为被触发,浏览器回到对应事件池中,把当前放在事件池的所有方法按序依次执行。

DOM2中,W3C规范中定义了3个事件阶段,依次是捕获阶段、目标阶段、冒泡阶段,IE9以后IE也支持了W3C规范。

EventTarget.addEventListener(event, function, useCapture)

绑定事件监听函数

  • event : (必需)事件名,支持所有 DOM事件 。
  • function:(必需)指定要事件触发时执行的函数。
  • useCapture:(可选)指定事件是否在捕获或冒泡阶段执行。true,捕获。false,冒泡。默认false。
EventTarget.removeEventListener()

删除EventTarget中事件侦听器。

EventTarget.dispatchEvent()

将事件分派到此EventTarget。

IE7,8的绑定事件方法使用attachEvent和detachEvent绑定和解绑监听函数

使用addEventListener绑定事件,与普通绑定的不同:

  1. addEventListener 能添加多个事件绑定,按顺序执行。
  2. addEventListener绑定后则可以用 removeEvenListener 取消;普通方式绑定事件后,不可以取消。

三、事件委托

事件委托是一种监听方式,又叫事件代理,通过监听一个父元素,来给不同的子元素绑定事件,减少监听次数。
比如我们要给ul中的li绑定事件,可以用for循环绑定事件,也可以通过事件委托,给ul绑定事件,因为事件流的关系,当点击了任何一个li节点,在冒泡节点都会触发ul的绑定事件,在ul的事件委托函数中通过Event对象的target属性可以获取到用户点击的td的信息。

<ul id="ul">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>
<script type="text/javascript">
  var oUl = document.getElementById('ul');
  var oLi = oUl.children;
  //传统方法
  for (var i = 0; i < oLi.length; i++) {
    oLi[i].onclick = function () {
      this.style.color='red';
    }
  }
  //事件代理
  oUl.onclick = function (event) {
   event.target.style.color='red';
  }
</script>

自定义事件

创建自定义事件

为了能够传递数据,一般使用 CustomEvent 构造器创建自定义事件,创建时需要两个参数:

  • 事件名称 字符串类型
  • 传递的数据对象
var myEvent = new CustomEvent('user_event_name', {
    detail:{
      title:'my event'
    },
    "bubbles" : true
  });

PS:自定义事件默认是不冒泡的
在这里插入图片描述

事件的监听

EventListener是根据事件的名称(事件对象的type属性)来进行监听的。

  var btn=document.getElementById('btn');
  btn.addEventListener('click',function () {});
  btn.addEventListener('user_event_name', function(event) {
    console.log('button绑定的事件处理函数',event)
  });
  document.addEventListener('user_event_name',function(event){
    console.log('document绑定的事件处理函数',event);
  });

事件的触发

自定义的事件不是JS内置的事件,需要在JS代码中去显式地使用 dispatchEvent方法触发,这个例子中由于设置事件允许冒泡,绑定在document上的事件处理函数也会被执行。

btn.dispatchEvent(myEvent);

可以使用全局方法getEventListeners()来查看元素的事件绑定
在这里插入图片描述
也可以在控制台-Elements-Event listeners面板中查看元素事件绑定
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值