解决方案

JS 之 事件Event对象详解(属性、方法、自定义事件)

seo靠我 2023-09-25 06:15:27

一、Event对象

1、简介

​ 事件event对象是指在浏览器中触发事件时,浏览器会自动创建一个event对象,其中存储了本次事件相关的信息,包括事件类型、事件目标、触发元素等等。浏览器创建完eventSEO靠我对象之后,会自动将该对象作为参数传递给绑定的事件处理函数,我们可以在事件处理函数中通过访问event对象的属性和方法,来获取事件的相关信息,并做出后续的逻辑处理。

​ 事件可以由用户操作触发,例如:鼠标SEO靠我事件、键盘事件等等;也可以通过 JS 脚本代码来触发,例如:通过element.click()方法,触发对应元素的点击事件;还可以由API生成,例如:动画完成后触发对应事件、视频播放被暂停时触发对应事SEO靠我件;最后还可以通过自定义事件来进行触发。这四种方式都会创建并传递event对象。

​ 除了我们自己绑定的事件处理函数之外,浏览器会对某些元素的某些事件存在默认处理,例如: a 标签的click点击事件,SEO靠我默认处理为跳转到链接的地址。当然我们也可以通过event对象的preventDefault() 方法来阻止浏览器的默认处理。

​ 我们还需要注意元素的嵌套关系,因为由于元素结构上的重叠,事件会随着嵌套关SEO靠我系依次传递,也就是事件冒泡和事件捕获。

2、Event对象示例 3、常用属性 ① event.bubbles(只读)

​ 该属性值为布尔值,表示当前事件是否会进行冒泡,tSEO靠我rue表示会冒泡,false表示不会冒泡。在前端事件大部分都是默认冒泡的,例如:click、mousedown等等;但也有一些特殊事件是默认不冒泡的,例如:focus、blur等等。

② event.cSEO靠我ancelBubble

​ 该属性值为布尔值,表示是否阻止当前事件的冒泡,默认为false,不阻止冒泡;设置为true则表示阻止当前事件冒泡。目前该属性已经完全被stopPropagetion()方法所SEO靠我取代,虽然部分浏览器处于兼容性的考虑依旧支持该属性,但后续随时有可能停止支持,因此尽量不要使用该属性。

③ event.cancelable(只读)

​ 该属性值为布尔值,表示当前事件的默认行为是否可以被SEO靠我取消,即是否能通过event.preventDefault()来取消默认行为,true表示可以取消,false表示不可以取消。

​ 如果是自定义事件,则在初始化事件时可以声明该事件是否可以被取消。

④ eSEO靠我vent.composed(只读)

​ 该属性值为布尔值,曾用名:scoped,表示当前事件是否可以打破屏障,从Shadow DOM冒泡传递到普通DOM,如果值为true表示当事件可以冒泡,即bubblSEO靠我es属性为true时,事件可以从Shadow DOM冒泡传递到普通DOM,此时可以通过composedPath()方法,来获取事件冒泡的路径;如果值为false,则表示事件不会跨越Shadow DOMSEO靠我与普通DOM的屏障进行冒泡。

​ 关于Shadow DOM的概念,在下面有进行讲解。

⑤ event.currentTarget(只读)

​ 该属性值为一个DOM,表示当前事件所绑定的那个DOM元素。而且要SEO靠我注意的是,该属性值只能在事件处理函数的过程中event.currentTarget直接调用使用,如果我们通过console.log(event)输出事件对象,如同上面的示例,我们会发现该属性值的值为nSEO靠我ull,无法访问到正确的值。我们在调试阶段,还可以通过在事件处理函数中设置debugger暂停代码执行,从而在输出的event对象上看到该属性正确的值。

⑥ event.target(只读)

​ 该属性值SEO靠我为一个DOM,表示触发当前事件的那个DOM元素。通常情况下该属性的值与event.currentTarget相同,但是如果当前事件是在冒泡或者捕获阶段被调用,则两者的值不同,target的值为触发事件SEO靠我的DOM,currentTarget的值为绑定事件的DOM。

​ 我们还可以借助target属性实现事件委托,又称事件代理,是指在要对一批子元素设置类似的事件处理器时,利用事件冒泡的机制,将事件处理器绑SEO靠我定到其公共父元素上,然后通过target属性,来区分是由哪个子元素触发的事件,并进行相应的逻辑处理。这样即可以大大的减少事件处理器的数量,提高性能,又可以动态地添加或删除子元素而不需要添加或删除相应的SEO靠我事件处理器,减少代码复杂度。

target与currentTarget在冒泡阶段对比

案例代码:

<div id="divBox"><div id="divClick">这里触发点击事件</div> SEO靠我 </div><script>// 事件绑定在子元素上 此时 target = document.querySelector(#divClick).addEventListener(clickSEO靠我, function (e) {console.log(e)console.log(e.target)console.log(e.currentTarget)})document.querySelecSEO靠我tor(#divBox).addEventListener(click, function (e) {console.log(e)console.log(e.target)console.log(e.SEO靠我currentTarget)}) </script>

执行结果:

⑦ event.defaultPrevented(只读)

​ 该属性值为布尔值,表示当前事件是否调用了event.preveSEO靠我ntDefault()方法,从而阻止了浏览器的默认行为,true表示已经调用过,false表示还未调用。

⑧ event.returnValue

​ 属性值为布尔值,表示当前事件的默认行为是否执行,该属性SEO靠我可读可写,true表示正常执行,false表示阻止默认行为。该属性是由IE率先引入,最后被收入web规范,该属性相当于event.defaultPrevented和event.preventDefauSEO靠我lt()的结合。

案例代码:

<a href="https://www.baidu.com" id="a0">不阻止默认行为</a> <a href="https://www.baidu.SEO靠我com" id="a1">event.returnValue阻止默认行为</a> <a href="https://www.baidu.com" id="a2">event.preveSEO靠我ntDefault()阻止默认行为</a><script>document.querySelector(#a0).addEventListener(click, function (e) {// 不阻SEO靠我止默认行为console.log(不阻止默认行为的e.returnValue---, e.returnValue)// 打断点 暂停页面跳转 方便查看控制台输出debugger})document.qSEO靠我uerySelector(#a1).addEventListener(click, function (e) {// 阻止默认行为e.returnValue = falseconsole.log(通过SEO靠我returnValue = false阻止默认行为的e.returnValue---, e.returnValue)})document.querySelector(#a2).addEventListSEO靠我ener(click, function (e) {// 阻止默认行为e.preventDefault()console.log(通过preventDefault()阻止默认行为的e.returnVaSEO靠我lue---, e.returnValue)}) </script>

执行结果:

⑨ event.eventPhase(只读)

​ 该属性值为整数数值,表示事件流的当前执行阶段,共分为四个阶SEO靠我段,每个阶段有不同的事件阶段常量,如下:

常量值描述Event.NONE0这个阶段,没有事件正在被处理Event.CAPTURING_PHASE1这个阶段是指事件捕获的过程,事件正在被目标元素的祖先对象SEO靠我处理,是从最外层的祖先元素到目标元素的过程,从Window、Document、…、目标元素的过程。Event.AT_TARGET2这个阶段是指到达目标元素的过程。如果 Event.bubbles 的值SEO靠我为 false,即事件不会冒泡,则对事件对象的处理在这个阶段后就会结束。Event.BUBBLING_PHASE3这个阶段是指事件冒泡的过程,从从目标元素到最外层的祖先元素的过程。

事件流的执行过程:

SEO靠我 当我们通过event.eventPhase获取当前事件流的执行阶段时,会直接获取到当前事件阶段常量的值,我们可以直接根据值判断事件流的执行阶段,也可以通过对比event.eventPhase与事件阶SEO靠我段常量是否强相等(===),判断事件流的执行阶段。

案例代码:

<div id="div0"><div id="div1">事件流演示</div> </div> <scriSEO靠我pt>// addEventListener设置第三个参数为true 表示在捕获阶段触发事件document.querySelector(#div0).addEventListener(click, SEO靠我function (e) {console.log(div0--, e)// 输出事件阶段常量的值console.log(捕获阶段的事件阶段常量---, e.eventPhase)// 判断事件阶段是SEO靠我否为捕获阶段console.log(e.eventPhase === Event.CAPTURING_PHASE)}, true)// addEventListener设置第三个参数为false或者不SEO靠我设置 表示在冒泡阶段触发事件document.querySelector(#div0).addEventListener(click, function (e) {console.log(div0--SEO靠我, e)// 输出事件阶段常量的值console.log(冒泡阶段的事件阶段常量---, e.eventPhase)// 判断事件阶段是否为冒泡阶段console.log(e.eventPhase =SEO靠我== Event.BUBBLING_PHASE)})// 目标元素document.querySelector(#div1).addEventListener(click, function (e) SEO靠我{console.log(div1--, e)// 输出事件阶段常量的值console.log(到达目标元素的事件阶段常量---, e.eventPhase)// 判断事件阶段是否为到达目标元素阶段cSEO靠我onsole.log(e.eventPhase === Event.AT_TARGET)}) </script>

执行结果:

event.timeStamp(只读)

​ 该属性值为一个数值SEO靠我,表示从文档加载完成,到当前事件被触发之间的的毫秒数,Chrome、Safari和Edge返回的是带有小数的毫秒数,FireFox返回的是不带小数的毫秒数。

​ 因为各大浏览器之间的返回值并不统一,所以SEO靠我不太建议使用该属性。

案例代码:

<div style="width: 200px;height: 30px;" id="div2">点击获取事件发生时的毫秒数</div><script>// 获取事件发SEO靠我生时的毫秒数document.querySelector(#div2).addEventListener(click, function (e) {console.log(事件发生时的毫秒数---, SEO靠我e.timeStamp)}) </script>

执行结果:

⑪ event.type(只读)

​ 该属性值是一个字符串,表示当前事件的类型,不区分大小写。

案例代码:

<div style="SEO靠我width: 200px;height: 30px;" id="div3">点击获取事件的type属性 </div><script>// 获取事件的type属性document.queSEO靠我rySelector(#div3).addEventListener(click, function (e) {console.log(事件的type属性---, e.type)}) SEO靠我</script>

执行结果:

⑫ event.isTrusted(只读)

​ 该属性值是一个布尔值,表示当前事件是由用户行为触发,还是通过JS脚本触发,true表示用户行为触发,false表示脚本触发。

SEO靠我例代码:

<div style="width: 200px;height: 30px;" id="div4">点击获取事件的isTrusted属性</div> <div id="div5SEO靠我"></div><script>// 获取用户手动触发时事件的isTrusted属性document.querySelector(#div4).addEventListener(click, funcSEO靠我tion (e) {console.log(用户手动触发时事件的isTrusted属性---, e.isTrusted)// 设置定时器模拟脚本触发事件setTimeout(() => {documeSEO靠我nt.querySelector(#div5).click();}, 1000)})// 获取脚本触发时事件的isTrusted属性document.querySelector(#div5).addESEO靠我ventListener(click, function (e) {console.log(脚本触发时事件的isTrusted属性---, e.isTrusted)}) </scripSEO靠我t>

执行结果:

4、常用方法 ① event.composedPath()

​ 该方法用来获取当前事件的事件传播路径,从触发元素到最外层Window,而且阻止冒泡的方法不会影响到事件的传播SEO靠我路径。如果Shadow DOM根节点触发事件,并且ShadowRoot.mode是关闭的,则获取的路径中将不包括Shadow DOM节点。

案例代码:

<div id="div0"><div id="diSEO靠我v0Son">验证target和currentTarget</div> </div><script>// 获取事件对象的事件路径document.querySelector(#div0SEO靠我Son).addEventListener(click, function (e) {// 阻止事件冒泡 但并不会影响事件的传播路径e.stopPropagation()// 通过e.composedSEO靠我Path()获取事件对象的事件路径console.log(e.composedPath())}) </script>

执行结果:

② event.preventDefault()

​ 该方法SEO靠我用来取消当前事件的默认行为,当然如果当前事件存在冒泡行为,即bubbles属性为true,那么事件的冒泡行为还是会继续向上传播,不会被影响。

案例代码:

<div id="div1"><input typSEO靠我e="checkbox" id="checkbox"> </div><script>// 阻止多选按钮的默认行为document.querySelector(#checkbox).adSEO靠我dEventListener(click, function (e) {e.preventDefault()})// 验证阻止默认行为后是否会继续冒泡document.querySelector(#dSEO靠我iv1).addEventListener(click, function (e) {console.log(阻止默认行为后会继续冒泡)}) </script>

执行结果:

③ eventSEO靠我.stopPropagation()

​ 该方法用来阻止当前事件在捕获阶段和冒泡阶段中的传播,如果点击了子元素,但是在子元素中阻止了事件的冒泡,那么父元素对应的事件不会被触发;如果点击了子元素,但是在父SEO靠我元素中阻止了事件的捕获传播,那么子元素对应的事件将不会被触发。

案例代码:

<div id="div2"><div id="div2Son">验证stopPropagation()方法阻止事件冒泡传播</SEO靠我div> </div> <div id="div3"><div id="div3Son">验证stopPropagation()方法阻止事件捕获传播</div> SEO靠我 </div><script>// 验证stopPropagation()方法阻止事件冒泡document.querySelector(#div2Son).addEventListener(cSEO靠我lick, function (e) {console.log(子元素阻止事件冒泡);e.stopPropagation()})// 验证stopPropagation()方法阻止事件冒泡后父元素是否SEO靠我接收到冒泡的事件document.querySelector(#div2).addEventListener(click, function (e) {console.log(父元素是否接收到冒泡的事SEO靠我件)})// 验证stopPropagation()方法阻止事件捕获传播document.querySelector(#div3).addEventListener(click, function (SEO靠我e) {console.log(父元素阻止事件捕获传播);e.stopPropagation()}, true)// 验证stopPropagation()方法阻止事件捕获后子元素是否接收到捕获的事件SEO靠我document.querySelector(#div3Son).addEventListener(click, function (e) {console.log(子元素是否接收到捕获传播的事件)}SEO靠我, true) </script>

执行结果:

④ event.stoplmmediatePropagation()

​ 该方法用来阻止当前事件的其他事监听器被触发,如果我们通过addEveSEO靠我ntListener()方法给同一个事件,增加多个事件监听器,那当该事件被触发时,多个事件监听器会按照添加的顺序依次执行。但如果我们在其中某个事件监听器绑定的函数中,执行event.stoplmmedSEO靠我iatePropagation()方法,那么位于该事件监听器之后的其他监听器将不会被触发。

案例代码:

<div id="div4">验证stopImmediatePropagation()法 SEO靠我 </div><script>// 验证stopImmediatePropagation()方法document.querySelector(#div4).addEventListener(cliSEO靠我ck, function (e) {console.log(第一个事件监听器);})document.querySelector(#div4).addEventListener(click, funcSEO靠我tion (e) {console.log(第二个事件监听器);// 阻止后续事件监听器的执行e.stopImmediatePropagation()})document.querySelector(SEO靠我#div4).addEventListener(click, function (e) {console.log(第三个事件监听器);}) </script>

执行结果:

5、ShadowSEO靠我 DOM

​ Shadow DOM 是Web components 的核心内容,用于构建独立的web组件,可以将一个DOM树和相应的CSS样式封装隔离起来,与页面的常规DOM相互隔离,不会出现影响和冲突SEO靠我。然后可以将封装的Shadow DOM附加到常规的DOM节点上。操作Shadow DOM 的方式与常规DOM并无太大区别,都可以给DOM添加子节点、设置属性,以及为节点添加自己的样式。唯一有所不同的是SEO靠我:Shadow DOM内部的元素除了设置 :focus-within之外,设置其他任何属性都不会影响到常规 DOM。

​ Shadow DOM 有以下四个主要概念:

Shadow host:一个常规的DOSEO靠我M节点,Shadow DOM将会附加在该节点上。Shadow tree:一个DOM树,即Shadow DOM 内部的DOM结构。Shadow boundary:Shadow DOM与常规DOM的分界线SEO靠我,是 Shadow DOM 结束的地方,也是常规 DOM 开始的地方。Shadow root :Shadow tree所代表的DOM树的根节点。

Shadow DOM主要概念图解:

​ 虽然Shadow SEO靠我DOM看起来比较陌生,但这并不是一个新特性,浏览器很早之前便在使用该特性,例如:<video>标签,虽然我们在DOM中只能看到一个单独的标签,但其实在该标签的Shadow DOM中,包含了进度条、播放SEO靠我按钮、倍速按钮等DOM结构。 Firefox(从版本 63 开始)、Chrome、Opera 、 Safari、Edge 都默认支持 Shadow DOM。

二、自定义事件

1、简介

​ 在日常开发中我们通SEO靠我常使用的都是浏览器提前定义好的事件,例如:点击事件click、失去焦点事件blur等等。当这些基础事件不能满足我们的业务需求时,我们也可以通过创建自定义Event事件对象来自定义相关事件。

​ 目前实现SEO靠我自定义事件的方式有两种:Event()构造函数和CustomEvent()构造函数。

​ 触发自定义事件的方式为:element.dispatchEvent(event)。

2、Event()

​ 构造函数SEO靠我Event(typeArg[,eventInit])用来创建一个新的event事件对象,该构造函数拥有两个参数:第一个参数typeArg为必填参数,参数值为DOMString类型,表示所创建事件的名称SEO靠我;第二个参数eventInit为可选参数,参数值为EventInit类型的对象数据,拥有三条可选属性:① bubbles:属性值为Boolean类型,默认值为false,表示创建的事件是否能进行冒泡。SEO靠我② cancelable:属性值为Boolean类型,默认值为false,表示创建的事件的行为是否可以被preventDefault()取消。③ composed: 属性值为为Boolean类型,默认SEO靠我值为false,表示创建的事件是否可以穿透Shadow DOM 与常规DOM的屏障,进行冒泡。

案例代码: <div class="div1"><div class="div1Son">SEO靠我验证自定义事件</div> </div><script>// 1、创建一个支持冒泡,支持取消,支持穿透 的look事件let myEvent = new Event(look, { "SEO靠我bubbles": true, "cancelable": true, "composed": true });// 2、监听自定义事件document.querySelector(.div1Son)SEO靠我.addEventListener(look, function (e) {console.log(监听到自定义事件----, e.type)})// 3、利用点击事件 去触发自定义事件documenSEO靠我t.querySelector(.div1Son).addEventListener(click, function (e) {// 触发自定义事件document.querySelector(.diSEO靠我v1Son).dispatchEvent(myEvent)})// 4、监听父元素是否收到冒泡的自定义事件document.querySelector(.div1).addEventListener(SEO靠我look, function (e) {console.log(父元素是否收到冒泡的自定义事件----, e.type)}) </script> 执行结果: SEO靠我 3、CustomEvent()

​ 构造函数CustomEvent(typeArg[,customEventInit])用来创建一个新的CustomEvent事件对象,该构造函数拥有两个参数:SEO靠我第一个参数typeArg为必填参数,参数值为DOMString类型,表示所创建事件的名称;第二个可选参数customEventInit,参数值为CustomEventInit 类型的对象数据,拥有四条SEO靠我可选属性:① bubbles:属性值为Boolean类型,默认值为false,表示创建的事件是否能进行冒泡。② cancelable:属性值为Boolean类型,默认值为false,表示创建的事件的行SEO靠我为是否可以被preventDefault()取消。③ composed: 属性值为为Boolean类型,默认值为false,表示创建的事件是否可以穿透Shadow DOM 与常规DOM的屏障,进行冒泡SEO靠我。④ detail:属性值为任意类型的数据,默认值为null,通常用来表示与当前事件相关的信息。

​ Event 接口是 CustomEvent 接口的父级接口,因此 CustomEvent 继承了 ESEO靠我vent 的所有属性和方法,并且在 Event 的基础上添加了一个 detail 属性,用于在事件处理程序中传递自定义数据。除此之外,CustomEvent 还允许我们在事件对象上添加自定义属性和方法SEO靠我,以便在事件处理程序中使用。这使得我们可以创建更灵活、更具体的事件类型,并在事件处理程序中访问和操作事件对象。

​ 总的来说:CustomEvent 是自定义的事件类型,可操作性强,可以更好地满足开发人SEO靠我员的特定需求,而 Event 则更适合表示标准的、通用的事件类型,可操作性弱。

案例代码: <div class="div2"><div class="div2Son">验证CustomSEO靠我Event()构造函数创建自定义事件</div> </div><script>// 利用CustomEvent()构造函数创建自定义事件// 1、创建一个支持冒泡,支持取消,支持穿透,SEO靠我具有自定义属性 的look事件let myEvent2 = new CustomEvent(look, {"bubbles": true, "cancelable": true, "composed"SEO靠我: false, detail: {info: 这是CustomEvent的detail属性, // 自定义属性getTime: function () { // 自定义方法return new DaSEO靠我te()}}});// 2、监听自定义事件document.querySelector(.div2Son).addEventListener(look, function (e) {console.lSEO靠我og(监听到自定义事件----, e)console.log(调用自定义事件上的自定义方法----, e.detail.getTime())})// 3、利用点击事件 去触发自定义事件documentSEO靠我.querySelector(.div2Son).addEventListener(click, function (e) {// 触发自定义事件document.querySelector(.divSEO靠我2Son).dispatchEvent(myEvent2)})// 4、监听父元素是否收到冒泡的自定义事件document.querySelector(.div2).addEventListener(SEO靠我look, function (e) {console.log(父元素是否收到冒泡的自定义事件----, e.type)}) </script> 执行结果:

三、相关资SEO靠我

事件参考

Event

CustomEvent

shadow DOM

:focus-within

“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2