JavaScript

您所在的位置:网站首页 事件的表示方法 JavaScript

JavaScript

2024-01-08 02:21| 来源: 网络整理| 查看: 265

原文:JavaScript | 事件对象—事件流、常用属性

在JavaScript中经常可以看到事件对象的使用,所以打算写一篇博客来记录下学习此知识点的过程。

什么是事件对象?

首先我们需要了解一下事件对象是什么,先来看下MDN给出的定义

Event 接口表示在 DOM 中出现的事件。

一些事件是由用户触发的,例如鼠标或键盘事件;而其他事件常由 API 生成,例如指示动画已经完成运行的事件,视频已被暂停等等。事件也可以通过脚本代码触发,例如对元素调用 HTMLElement.click() 方法,或者定义一些自定义事件,再使用 EventTarget.dispatchEvent() 方法将自定义事件派发往指定的目标(target)。—— MDN-Event

可以看到事件对象是一个对象,而这个对象记录了事件触发的时候的相关信息,比如:

触发鼠标点击事件的时候,事件对象记录了鼠标的位置相关的信息 触发键盘事件的时候,事件对象会记录下用户按下的对应的按键的相关信息 如何使用(获取)事件对象?

通过DOM LV2的方式添加绑定事件的时候,回调函数的第一个参数就是事件对象,一般可以将其命名为e、event

document.querySelector('#test', function(e){ console.log(e); }); 事件流

事件流描述了页面接收事件的顺序。——《JavaScript高级程序设计》

假如页面上有一个元素,该元素触发事件的时候,首先水发生事件捕获,然后才是事件冒泡。

截图转存失败,建议直接上传图片文件

事件冒泡

当一个元素触发事件后,会依次向上调用所有父级元素的同名事件

截图转存失败,建议直接上传图片文件

事件冒泡是默认存在的

验证:

比如现在页面上有这几个元素,对应的CSS以及HTML如下

CSS:

#test1 { width: 600px; height: 600px; background-color: red; } #test2 { width: 400px; height: 400px; background-color: yellow; } #test3{ width: 200px; height: 200px; background-color: blue; }

HTML:

截图转存失败,建议直接上传图片文件

现在给分别给这几个元素添加点击事件

JS:

let test1 = document.querySelector('#test1'); let test2 = document.querySelector('#test2'); let test3 = document.querySelector('#test3'); test1.addEventListener('click',function(){ console.log('test1'); }); test2.addEventListener('click',function(){ console.log('test2'); }); test3.addEventListener('click',function(){ console.log('test3'); });

此时点击蓝色的部分(div#test3),就会依次输出test3,test2,test1的消息。

如果点击黄色的部分(div#test2),就会依次输出test2,test1的消息。

如果点击红色的部分(div#test1),就会只输出test1的消息。

可以看到,结果符合事件冒泡的顺序div#test3->div#test2->div#test1(从里到外)。

事件捕获

从DOM的根元素开始去执行对应的事件 (从外到里)

截图转存失败,建议直接上传图片文件

注:

实际上,所有浏览器都是从 window 对象开始捕获事件,而 DOM2 Events 规范规定的是从 document 开始

由于旧版本浏览器不支持,因此实际当中几乎不会使用事件捕获。通常建议使用事件冒泡,特殊情 况下可以使用事件捕获。

相关内容详细请见——《JavaScript高级程序设计》

事件捕获需要写对应的代码才能开启,如何开启事件捕获如下:

document.querySelector('#test1').addEventListener(eventType, callBack, useCapture)

说明:

参数3useCapture接受一个布尔值,代表是否开启事件捕获 参数3为true的时候代表开启事件捕获(默认状态为false)

❕注意:默认DOM 0级,也就是element.onclick = function(){}的写法,只有冒泡没有捕获。

验证:

针对刚才冒泡的js代码做如下修改,开启事件捕获

test1.addEventListener('click',function(){ console.log('test1'); }, true); test2.addEventListener('click',function(){ console.log('test2'); }, true); test3.addEventListener('click',function(){ console.log('test3'); }, true);

此时点击蓝色的部分(div#test3),就会依次输出test1,test2,test3的消息。

如果点击黄色的部分(div#test2),就会依次输出test1,test2的消息。

如果点击红色的部分(div#test1),就会只输出test1的消息。

可以看到,结果符合事件捕获的顺序div#test1->div#test2->div#test3(从外到里)。

阻止停止冒泡,捕获

如果只想把对应的事件限制在子元素内,不想触发父级的事件,那么旧需要阻止事件流动。

通过e.stopPropagation()方法,就可以阻止事件冒泡

❕注:不推荐使用event.cancelBubble,该特性已经从 Web 标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性。—— MDN-Event.cancelBubble

比如对于刚才的案例,如果指向要点击事件的触发只限制在子元素内,比如只想要div#test3点击的时候,只输出test3,那就可以加上这个方法。

对于事件捕获(不常用):

test1.addEventListener('click',function(e){ console.log('test1'); e.stopPropagation(); }, true); test2.addEventListener('click',function(e){ // console.log('test2'); }, true); test3.addEventListener('click',function(e){ console.log('test3'); // e.stopPropagation(); }, true);

加上这个方法后不管点击哪里,都只会输出test1了。

对于事件冒泡:

test1.addEventListener('click',function(e){ console.log('test1'); }); test2.addEventListener('click',function(e){ console.log('test2'); }); test3.addEventListener('click',function(e){ console.log('test3'); e.stopPropagation(); });

现在点击div#test3就只会输出test3了。

阻止事件默认行为

如果不想要a标签点击直接跳转,表单点击不直接提交可以使用下面的方法

语法:

e.preventDefault()

验证:

HTML:

click link

JS:

let btn = document.querySelector('button'); let a = document.querySelector('a'); btn.addEventListener('click', function(e){ // 阻止表单提交 e.preventDefault(); }); a.addEventListener('click', function(e){ // 阻止链接点击默认跳转 e.preventDefault(); }) 事件代理(委托)

可以利用事件冒泡的特性,可以只使用一个事件处理程序来管理一种类型的事件。——《JavaScript高级程序设计》

给所有元素共同的祖先节点添加一个事件处理程序(可以提高性能)

使用:通过事件对象的target属性(e.target),可以得到事件真正的触发者。

使用场景:

ul .active { color: red; border: 1px solid rgb(255, 28, 28); } 第1个 第2个 第3个 第4个 第5个 第6个

比如页面上有这样一个tag栏,想要点击的时候对应的tag栏变色的效果,这个时候正常情况下可以使用,for循环的形式依次为每个li元素添加点击事件:

// 获取所有li元素组成的NodeList let lis = document.querySelectorAll('li'); // 给每个NodeList添加点击事件 lis.forEach((item) => { item.addEventListener('click', function(){ // 去除页面上已经激活的li样式 if (document.querySelector('.active')) { document.querySelector('.active').classList.remove('active'); } // 激活当前li的样式 this.classList.add('active'); }); });

同样的使用事件代理也可以解决问题,并且可以提高网页性能,不需要在使用循环的形式来给每个元素做绑定事件了,对应的JS代码如下:

// 事件代理 let ul = document.querySelector('ul'); ul.addEventListener('click', function (e) { // 如果点击的目标元素是li标签则进行样式修改 if (e.target.tagName == 'LI') { // 去除页面上已经激活的li样式 if (document.querySelector('.active')) { document.querySelector('.active').classList.remove('active'); } // 激活当前li的样式 e.target.classList.add('active'); } });

🤖了解:e.currentTarget返回事件的监听者(事件绑定的对象)。

事件对象中的常用属性 获取事件事件触发类型 type:获取当前触发的事件的类型(只读) 获取当前坐标的属性(点击事件) offsetX/offsetY:返回的是点击时候相对点击的元素左上角的相对位置(包含外边距)的坐标。 pageX/pageY:返回的是整个文档的坐标,如果此时页面比较长可以获取文档中鼠标的坐标。 clientX/clientY:返回的是鼠标点击的时候光标浏览器可视范围相对左上角的坐标。 screenX/screenY:返回的是鼠标点击的时候光标相对屏幕左上角的坐标。 layerX/layerY:往上找有定位属性的父元素的左上角(自身有定位属性的话就是相对于自身),都没有的话,就是相对于body的左上角的坐标。

PS:有关于这块的内容可以参考笔者写的另一篇文章——> 链接在这里

获取按键的属性(键盘事件) key:获取用户按下的物理按键的值(只读) keyCode(不建议使用):返回按键对应的编号。(注:该功能已从Web标准中删除,尽管一些浏览器可能仍然支持它,但它正在被丢弃。) target属性与currentTarget属性 target:返回事件真正的触发者 currentTarget:返回事件的监听者(事件绑定的对象) eventPhase属性

eventPhase:表示事件流当前处于哪一个阶段。

返回值含义0此时没有事件在处理1事件处于捕获阶段2事件已经到达触发者3事件处于冒泡阶段

测试:

1、事件冒泡

HTML:

CSS:

#test3{ width: 200px; height: 200px; background-color: blue; }

JS:

let test3 = document.querySelector('#test3'); test3.addEventListener('click',function(e){ console.log('div e.eventPhase:' + e.eventPhase); }); document.addEventListener('click', function(e){ console.log('doc eventPhase:' + e.eventPhase); });

点击div#test3依次输出

div e.eventPhase:2 doc eventPhase:3

2、事件捕获

对上面的代码做一点修改

let test3 = document.querySelector('#test3'); test3.addEventListener('click',function(e){ console.log('div e.eventPhase:' + e.eventPhase); }); document.addEventListener('click', function(e){ console.log('doc eventPhase:' + e.eventPhase); }, true);

点击div#test3依次输出

doc eventPhase: 1

div e.eventPhase: 2

button属性 e.button:MouseEvent.button 是只读属性,它返回一个值,代表用户按下并触发了事件的鼠标按键。 返回值含义0鼠标左键1鼠标中键2鼠标右键

测试代码:

let test3 = document.querySelector('#test3'); test3.addEventListener('mouseup',function(e){ if (e.button == 2) { console.log('click the right button'); } else if (e.button == 0){ console.log('click the left button'); } else if (e.button == 1){ console.log('click the middle button'); } else { console.log('????'); } }); 参考文献

《JavaScript高级程序设计》(第四版)

浅谈事件冒泡和事件捕获

说说事件冒泡和事件捕获

事件冒泡(阻止冒泡)和事件捕捉(阻止捕获)

javascript:Event事件对象

【js】event(事件对象)详解



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3