JS高程 -- chapter13( 事件 )

本文详细介绍了JavaScript中的事件流,包括事件冒泡和事件捕获,以及DOM2级事件流。同时,讲解了事件处理程序的四种方式:HTML事件处理程序、DOM0级事件处理程序、DOM2级事件处理程序和IE事件处理程序。此外,还阐述了事件对象在DOM和IE中的差异,并列举了多种事件类型,如UI事件、鼠标事件、键盘事件等。最后讨论了事件委托和内存性能优化策略。
摘要由CSDN通过智能技术生成

事件流


事件流描述的是页面中元素触发事件时,接收事件的顺序,IE 提出了 冒泡 事件流,NetScape 则提出了 捕获 事件流

1. 事件冒泡

IE 的事件流叫做 事件冒泡,即事件是从最具体的元素开始,逐渐向上冒泡到祖先元素

事件冒泡

2. 事件捕获

NetScape 提出的事件流叫做 事件捕获,即事件从 不具体的元素开始,直到具体的触发元素,其旨在 事件 到达目标元素之前将其截获

事件捕获

3. DOM 事件流

DOM2级事件 规定事件流包括 三个阶段: 事件捕获阶段,处于目标阶段,事件冒泡阶段

在 DOM事件流 中,实际的目标元素捕获阶段 不会接收到事件下一个阶段是 处于目标元素,这阶段在事件处理中被当成冒泡阶段的一部分,然后冒泡阶段发生

DOM事件流

尽管 DOM2级 规范规定 捕获阶段不应该涉及目标元素,但 高版本浏览器都会在 捕获阶段触发事件对象上的事件,结果就是有两个机会在目标对象上面操作事件

 

事件处理程序


1. HTML 事件处理程序

<script>
	function show(){
		......
	}
</script>
<input type="button" onclick="show()"/>

上述代码在按钮被点击时就会调用,这种绑定事件的方式首先会 创建一个封装这元素属性值的函数,这个函数内部有一个局部对象 event,可以 访问到事件触发时的事件对象,这个对象不用自己定义或者从参数列表中获取,并且该函数内部的 this 值指向触发事件的元素

不建议在HTML中绑定事件

 

2. DOM0 级事件处理程序

每个元素都有自己的事件处理程序属性( onclick… ),所以传统的通过 JS 添加事件处理函数的方式就是,将一个函数赋值给一个事件处理程序属性

oDiv.onclick = function(){
	......
}

使用 DOM0级 方法指定处理函数被认为是元素的方法,这时候事件处理程序是在元素的作用域中运行,即函数的 this 指向元素本身

以这种方式添加的处理函数会在冒泡阶段被处理,也可以将其设置为 null 来移除处理函数

 

3. DOM2级事件处理程序

DOM2级事件 定义了两个方法: addEventListener()、removeEventListener(),两个函数都可以接收 3 个参数,要处理的事件名( 事件程序属性去掉 on )、处理函数、一个布尔值,可以添加多个事件监听函数,事件触发时按照添加顺序执行

第三个参数为 true ,则表示在捕获阶段调用事件处理程序,为 false ,则表示在冒泡阶段调用处理程序

通过 addEventListener() 添加的处理函数只能由 removeEventListener() 来移除,移除时传入的参数与添加时的处理函数相同,这意味着添加的匿名函数 无法 被移除

 
大多数情况下,都是将事件添加到 冒泡阶段,这样可以最大限度的兼容各种浏览器

 

4. IE 事件处理程序

IE 中相似的两个方法是 attachEvent()、detachEvent(),两个方法都接收两个参数,事件名、处理函数,事件名和元素的事件程序属性一致( onclick… ),也可以添加多个处理函数,触发时按照添加顺序反序执行

attachEvent() 和 DOM0级 事件绑定的区别在于,attachEvent() 的处理函数作用域是全局的( this 指向 window ),而不是目标元素

 

事件对象


1. DOM 中的事件对象

无论使用什么方法 DOM0级 或者 DOM2级 方式指定事件处理函数,都会传入 event 对象( 事件处理函数最多只能接收一个参数,即为 event 对象 )

DOM0: xx.onclick = function(event){ ... }
DOM2: xx.addEventListener('click', function(event){ ... }, false)

也可以不显示指定 event 对象传参,函数内部依然可以直接使用
DOM0: xx.onclick = function(){ ... }
DOM2: xx.addEventListener('click', function(){ ... }, false)

所有事件类型的事件对象都有的属性、方法:

属性/方法类型读/写说明
bubblesBoolean只读事件是否冒泡
cancelableBoolean只读是否 可以 取消冒泡
currentTargetElement只读事件处理程序当前正在处理事件的元素
defaultPreventedBoolean只读是否调用了 preventDefault( DOM3新增 )
detailInteger只读与事件相关的细节信息
eventPhaseInteger只读调用处理函数的阶段,1: 捕获、2: 处于目标、3: 冒泡
preventDefault()Function只读取消事件默认行为
stopImmediatePropagation()Function只读取消事件进一步捕获、冒泡,同时阻止任何事件处理程序被调用( DOM3新增 )
stopPropagation()Function只读取消事件进一步捕获、冒泡
targetElement只读事件的目标元素
trustedBoolean只读true 表示为浏览器生成,反之表示由开发人员通过 JS 生成( DOM3新增 )
typeString只读触发的事件类型
viewAbstractView只读指向 window

target vs currentTarget
 
<div> <span>123</span> </div> 为div 绑定了点击事件
 
span 元素被点击时,触发点击事件,然后冒泡到 divdiv 的点击事件被触发,此时 event 对象的 currentTarget 就指向 divtarget 指向 span
 
currentTarget 为事件处理函数触发时所在的对象( 因为可能捕获下去,或者冒泡上来,触发当前元素的相应事件 ),target 为触发事件的元素,当该元素也绑定了事件的时候,这两个的值是相等的,都指向触发事件的元素
 
处理函数内部,this 值始终指向 currentTarget 元素,因为它是处理函数的作用元素

 

2. IE 中的事件对象

访问 IE 中的 event 对象取决于使用什么方式绑定处理函数,使用 DOM0级 方式绑定,则 event 对象作为 window的一个属性存在,使用 window.event 来获取,使用 attachEvent 绑定则作为一个参数传入

DOM0:
	xx.onclick = function() { var event = window.event }

attachEvent:
	xx.attachEvent("onclick",function(event){ ... })

IE 中 event 对象都有的属性、方法:

属性/方法类型读/写说明
cancelBubbleBoolean读/写默认为 false,设置为 true 即可 取消冒泡
returnValueBoolean读/写默认为 true,设置为 false 即可 阻止默认行为
srcElementElement只读事件触发的元素,参考 target
typeString只读触发的事件类型

 

事件类型


DOM3级 规定了以下几类事件:

  • UI事件: 用户与界面发生交互时触发
  • 焦点事件: 元素获得或者失去焦点时触发
  • 鼠标事件
  • 滚轮事件
  • 文本事件: 在文档中输入文本时触发
  • 键盘事件
  • 变动事件: 底层 DOM 结构发生变化时触发

1. UI 事件

  • load: 页面完全加载后在 window 对象上触发、图像加载完成后在 img 元素上触发
  • unload: 页面完全卸载后在 window 对象上触发
  • error: 发生 JS 错误时在 window 对象上触发、无法加载图片时在 img 元素上触发、
  • select: 用户选择文本框( input 或者 textarea )中的一个或多个文字时触发
  • resize: 窗口大小变化时在 window 对象上触发
  • scroll: 当用户在带滚动条的元素上滚动时,在该元素上触发
1. load

当页面完全加载完毕( 包括所有图像、JS文件、CSS文件等外部资源 ),才会触发 window 的 load 事件

新图像元素 不一定要从添加到文档后才开始下载,只要设置了 src 属性就会开始下载

高版本浏览器中, script 标签也支持 load 事件,只有为 script 标签设置了 src 属性,并且添加到文档中后,才会开始下载

 

2. unload

这个事件在文档被 完全卸载 之后触发,只要用户从一个页面跳转到另一个页面,这个事件就会被触发

 

2. 焦点事件

  • blur: 元素失去焦点时触发,不会冒泡
  • focus: 元素获得焦点时触发,不会冒泡
  • focusin: 元素获得焦点时触发,与 focus 等价,冒泡
  • focuseout: 元素失去焦点时触发,与 blur 等价,冒泡

 
从页面中一个元素移动到另一个元素,会依次触发以下事件:

  1. focusout,在失去焦点的元素上触发
  2. focusin,在获得焦点的元素上触发
  3. blur,在失去焦点的元素上触发
  4. DOMFocusOut( opera),在失去焦点的元素上触发
  5. focus,在获得焦点的元素上触发
  6. DOMFocusIn( opera ),在获得焦点的元素上触发

 

3. 鼠标与滚轮事件

DOM3级事件 定义了 9 个鼠标事件:

  • click: 用户单击 主鼠标( 左键 ) 或者 按下回车键时触发( 需要获得焦点 )
  • dblclick: 用户双击 主鼠标 时触发
  • mousedown: 用户按下任意鼠标按钮触发
  • mouseenter: 鼠标首次移动到元素范围内触发,不冒泡
  • mouseleave: 鼠标移动到元素范围之外时触发,不冒泡
  • mousemove: 鼠标指针在元素范围内移动时触发
  • mouseout: 鼠标指针位于一个元素上方,将其移入另一个元素时触发
  • mouseover: 鼠标指针位于一个元素 外部,首次移入另一个元素边界之内时触发
  • mouseup: 用户释放鼠标按钮时触发
mouseover/out  VS  mouseenter/leave

1. mouseover/out 会冒泡,而 mouseenter/leave 则不会冒泡
2. 从外部移入到子元素时,会触发 子元素的 mouseover 和 本身的 mouseenter
3. 从外部移入到元素内时,先触发 mouseover,后触发 mouseenter;离开时先触发 mouseout,后触发 mouseleave
4. 从元素内部移入到子元素时,会触发 子元素的 mouseover 和 自身的 mouseout
5. 从子元素移入到元素内部时,会 触发 子元素的 mouseout 和 自身的 mouseover

 
只有在同一个元素上相继触发 mousedown、mouseup 事件,才会触发一次 click 事件,如果 mousedown、mouseup 中的一个被取消,就不会触发 click 事件

类似,只有连续触发了两次上述循环( 触发两次 click 事件 ),dblclick 事件才会被触发一次

它们的触发顺序始终如下:

  1. mousedown
  2. mouseup
  3. click
  4. mousedown
  5. mouseup
  6. click
  7. dblclick
1. 客户区坐标位置

鼠标事件都是在浏览器视口的特定位置发生的,这个位置信息保存在 event 事件对象的 clientXclientY 两个属性上,它们分别表示鼠标事件发生时,鼠标光标距离可视区( 不包括滚动的距离 ) 的 左侧 和 上方的距离

 

2. 页面坐标位置

通过 clientXclientY 两个属性可以知道,鼠标在位于可视区的什么位置产生了事件,而通过 pageXpageY 这两个属性,则可以知道鼠标位于页面的什么位置产生了事件( 包括滚动距离 )

pageXpageY 相当于 clientX + scrollLeftclientY + scrollTop

 

3. 屏幕坐标位置

screenXscreenY 两个属性可以确定事件发生时,鼠标距离屏幕左侧和上方的距离

event.screenX、event.screenY

 

4. 修改键

shift、ctrl、alt、meta( windows: windows、mac: cmd ) 这四个修改键允许我们在其按下时触发鼠标事件的不同行为( 采取不同的操作 ),DOM 规定了四个属性来表示它们的状态: shiftKeyctrlKeyaltKeymetaKey,触发事件时其被按下则相应的属性为 true,否则为 false

IE8 及之前不支持 metaKey 属性

 

5. 相关元素

因为 mouseovermouseout 两个事件会涉及到其他元素,所以 event 对象有一个 只对这两个事件 才有值的属性: relatedTarget,这个属性保存了相关元素的信息,对于其他事件,这个属性的值为 null

IE8及之前 提供了 fromElement ( mouseover )toElement ( mouseout ) 属性来保存相同的信息

对于 mouseover 来说,事件的主目标是获得光标的元素,所以 relatedTarget 指向失去光标的元素

对于 mouseout 来说,事件的主目标是失去光标的元素,所以 relatedTarget 指向获得光标的元素

 

6. 鼠标按钮

对于 mousedownmouseup,事件对象 提供了 一个 button 属性来判断用户 按下 或者 释放 了哪一个鼠标按钮,其中,0 代表主属性按钮,1 表示按下了中间的滑轮按钮, 2 表示按下了次鼠标按钮

 

7. 事件详细信息

事件对象的 detail 属性可以表示鼠标事件在该元素的当前位置发生了多少次( click 触发一次算一次单击 ),在 mousedownmouseup 触发的中间移动了位置,则 detail 属性重置为 0

 

8. 鼠标滚轮事件

当用户通过鼠标滚轮与页面交互,在垂直方向上滚动页面时,就会触发 mousewheel 这个事件。

这个事件的事件对象 会包含一个 wheelDelta 属性,当用户向前滚动滑轮时,这个属性的值是 正数( 120的倍数 )向后滚动滑轮时,这个属性的值是 负数( -120的倍数 )

 

9. 触摸设备

***对于移动设备

  1. 不支持 dblclick 事件
  2. 轻击 可单击元素( 单击可产生默认操作的元素如按钮、链接等,或者已经制定了 click 事件的元素 ) 会触发 mousemove 事件,若因此导致内容变化,则不会再触发其他事件;如果屏幕没有因此变化,则会相继触发 mousedownmouseupclick 事件
  3. mousemove 事件 也会触发 mouseovermouseout 事件
  4. 两个手指放在屏幕上,且页面随手指移动而滚动时会触发 mousewheelscroll 事件

 

4. 键盘与文本事件

  • keyDown: 按下 任意键 触发,按住不放则会一直触发
  • keyPress: 按下 字符键 触发,按住不放会一直触发
  • keyUp: 释放按键时触发

只有一个文本事件 textInput,其用意是在文本显示给用户之前拦截文本,其会在文本插入文本框 之前 触发

 
按下 字符键 时,先触发 keuDown,然后 keyPress,最后 keyUp

按下 非字符键 时,先触发 keyDown,然后 keyUp

 

5. HTML5 事件

1. contextmenu

这个事件用于表示何时显示上下文菜单,以及替换默认上下文菜单而提供自定义上下文菜单

由于这个事件是 冒泡 的,所以可以在 document 上监听,然后做对应的操作

 

2. beforeunload

这个事件会在页面卸载之前触发,可以通过它来取消页面的卸载,但是,不能完全取消,否则就相当于不让用户离开这个页面了,所以控制权在用户手中

这个事件会弹出一个对话框让用户选择,对话框中的内容可以通过监听函数的 返回值 return xx 或者 event.returnValue = xx( IE、FF ) 来确定

 

3. DOMContentLoad

DOMContentLoad 在形成完整的 DOM树 之后就会触发,不会理会资源( JS、CSS、图片 )是否下载完毕,此事件一定先于 load 事件触发

 

4. readystatechange

这个事件的目的是为 文档或者元素 提供与加载状态有关的信息,拥有此事件的对象都有一个 readyState 属性,其值可能是下面几个:

  • uninitialized ( 未初始化 ): 对象存在但未初始化
  • loading: 对象正在加载数据
  • loaded: 加载数据完毕
  • interactive ( 交互 ): 可以才做对象了,但还没完全加载
  • complete: 对象加载完毕

这个事件的 event 对象不会提供任何信息,也没有目标对象

scriptlink 元素也支持这个事件

 

5. hashchange

用于监听 URL 中的 hash值的变化,必须在 window 对象上监听此事件,该事件的事件对象会有 event.oldURLnewURL 两个属性,但最好使用 location 对象来确定改变后的值

 

6. 设备事件

1. 触摸事件
  • touchstart: 当手指触摸屏幕时触发,即使已经有手指触摸屏幕了
  • touchmove: 当手指在屏幕上移动时触发,调用 preventDefault() 可以阻止滚动
  • touchend: 手指离开屏幕时触发

上面的几个事件都会 冒泡,并且以 DOM 兼容方式实现,每个事件的事件对象都包含鼠标事件的常见属性

 
用于跟踪触摸的属性

  • touches: 当前跟踪的触摸操作的 Touch 对象的数组
  • targetTouchs: 特定于事件目标的 Touch 对象的数组
  • changeTouches: 自上次触摸以来发生了什么改变的 Touch 对象的数组

 
Touch 对象的属性:

  • clientX
  • clientY
  • pageX
  • clientY
  • screenX
  • screenY
  • identifier: 标识触摸的唯一 ID
  • target: 触摸的 DOM 节点元素

touchend 事件触发时,touches 中已经没有 Touch 对象了,因为已经没有活动的 Touch 对象了,此时可以使用 changeTouches 集合

 
在触摸屏上发生事件时,触发顺序如下

  1. touchstart
  2. mouseover
  3. mousemove ( 一次 )
  4. mousedown
  5. mouseup
  6. click
  7. touchend

 

2. 手势事件
  • gesturestart: 一个手指在屏幕上,另一个手指也触摸屏幕时触发
  • gesturechange: 任何一根手指发生移动时触发
  • gestureend: 任何一根手指离开屏幕

每个手势事件的事件对象都包含鼠标事件对象的标准属性,还额外提供了两个属性:

  1. rotation: 手指变化引起的旋转角度变化,正值表示顺时针,负值表示逆时针
  2. scale: 表示手指间距离的变化情况,从 1 开始

内存和性能

在 JS 中,添加到页面上的事件处理程序的数量会直接关系到页面的性能,首先,每个函数都是对象,都会占用内存,内存中对象越多,性能越差; 其次,必须事先指定所有事件处理程序而导致的 DOM 访问次数,会延迟页面交互就绪的时间

1. 事件委托

事件委托利用 事件冒泡 机制,在祖先节点上添加处理函数,而不用为每个具体元素添加处理函数

适合采用事件委托的事件:clickmousedownmouseupkeydownkeyupkeypress

事件委托可以处理新添加的子节点需要手动添加处理程序的问题( 处理已经在祖先节点写好,添加的新节点的事件会冒泡到祖先节点执行 )

 

2. 移除处理程序

有可能会在内存中保留过时不用的事件处理程序,其引用的内存不会被释放,有两种可能导致该问题:

  1. removeChild()、replaceChild() 方法移除子元素,但没有移除其事件处理程序,导致它们互相引用
  2. innerHTML 直接替换节点内容,也有可能导致子节点和其事件处理程序占用的内存不会被释放

在移除 DOM元素的时候将其的事件处理属性设置为 null,或者移除其事件处理函数

 

模拟事件

可以使用 JS 在任意时刻来触发特定的事件,而此时的事件就如同浏览器穿件的事件一样,该冒泡的还是会冒泡,而且能够导致浏览器执行已经指定的处理它们事件的事件处理程序( IE9+ )

1. DOM 中的事件模拟

可以在 document 对象上使用 createEvent() 来创建 event 对象,该方法接收一个 表示要创建的事件类型的字符串UIEventsMouseEventsMutationEventsHTMLEvents

创建了 event 对象之后,需要使用对应类型的特定方法来初始化该对象的有关信息:

  • 鼠标事件document.createEvent("MouseEvents").initMouseEvent( type, ...args )
  • HTML事件document.createEvent("MouseEvents").initEvent( type, ...args )
以下是对提供的参考资料的总结,按照要求结构化多个要点分条输出: 4G/5G无线网络优化与网规案例分析: NSA站点下终端掉4G问题:部分用户反馈NSA终端频繁掉4G,主要因终端主动发起SCGfail导致。分析显示,在信号较好的环境下,终端可能因节能、过热保护等原因主动释放连接。解决方案建议终端侧进行分析处理,尝试关闭节电开关等。 RSSI算法识别天馈遮挡:通过计算RSSI平均值及差值识别天馈遮挡,差值大于3dB则认定有遮挡。不同设备分组规则不同,如64T和32T。此方法可有效帮助现场人员识别因环境变化引起的网络问题。 5G 160M组网小区CA不生效:某5G站点开启100M+60M CA功能后,测试发现UE无法正常使用CA功能。问题原因在于CA频点集标识配置错误,修正后测试正常。 5G网络优化与策略: CCE映射方式优化:针对诺基亚站点覆盖农村区域,通过优化CCE资源映射方式(交织、非交织),提升RRC连接建立成功率和无线接通率。非交织方式相比交织方式有显著提升。 5G AAU两扇区组网:与三扇区组网相比,AAU两扇区组网在RSRP、SINR、下载速率和上传速率上表现不同,需根据具体场景选择适合的组网方式。 5G语音解决方案:包括沿用4G语音解决方案、EPS Fallback方案和VoNR方案。不同方案适用于不同的5G组网策略,如NSA和SA,并影响语音连续性和网络覆盖。 4G网络优化与资源利用: 4G室分设备利旧:面对4G网络投资压减与资源需求矛盾,提出利旧多维度调优策略,包括资源整合、统筹调配既有资源,以满足新增需求和提质增效。 宏站RRU设备1托N射灯:针对5G深度覆盖需求,研究使用宏站AAU结合1托N射灯方案,快速便捷地开通5G站点,提升深度覆盖能力。 基站与流程管理: 爱立信LTE基站邻区添加流程:未提供具体内容,但通常涉及邻区规划、参数配置、测试验证等步骤,以确保基站间顺畅切换和覆盖连续性。 网络规划与策略: 新高铁跨海大桥覆盖方案试点:虽未提供详细内容,但可推测涉及高铁跨海大桥区域的4G/5G网络覆盖规划,需考虑信号穿透、移动性管理、网络容量等因素。 总结: 提供的参考资料涵盖了4G/5G无线网络优化、网规案例分析、网络优化策略、资源利用、基站管理等多个方面。 通过具体案例分析,展示了无线网络优化中的常见问题及解决方案,如NSA终端掉4G、RSSI识别天馈遮挡、CA不生效等。 强调了5G网络优化与策略的重要性,包括CCE映射方式优化、5G语音解决方案、AAU扇区组网选择等。 提出了4G网络优化与资源利用的策略,如室分设备利旧、宏站RRU设备1托N射灯等。 基站与流程管理方面,提到了爱立信LTE基站邻区添加流程,但未给出具体细节。 新高铁跨海大桥覆盖方案试点展示了特殊场景下的网络规划需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值