博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript事件
阅读量:4180 次
发布时间:2019-05-26

本文共 6253 字,大约阅读时间需要 20 分钟。

JavaScript事件

对于事件来讲,首先,我们需要了解这样几个概念:事件;事件处理程序;事件类型;事件流;事件冒泡;事件捕获;事件对象;事件模拟,事件方面的性能优化(事件委托、移除事件处理程序);

事件的概念

事件:指的是文档或者浏览器窗口中发生的一些特定交互瞬间。我们可以通过监听器(或者处理程序)来预定事件,以便事件发生的时候执行相应的代码。

事件处理程序:我们用户在页面中进行的点击这个动作,鼠标移动的动作,网页页面加载完成的动作等,都可以称之为事件名称,即:click、mousemove、load等都是事件的名称。响应某个事件的函数则称为事件处理程序,或者叫做事件监听器。

实例:具体解释见代码注释:

事件
理解事件的基本概念

关于事件处理程序,从最初的发展到现在,经历了几次的变化。

事件处理程序的名字是以“on”开头,因此click事件的处理程序就是onclick。在最初,是使用HTML事件处理程序的,也就是说,某个元素(如div),支持的每一种事件,都可以使用一个与相应事件处理程序同名的HTML特性来制定(也就是标签的一个属性),这个特性的值就是能够执行的JavaScript代码。例如:

HTML事件

HTML事件处理程序

当然,我们也可以再οnclick=””当中进行函数的调用。(不建议使用这种HTML事件)

在DOM0级事件处理程序推出之后,广为各个用户的使用,但是,却出现了这样一个问题,当我希望为同一个元素/标签绑定多个同类型事件的时候(如,为上面的这个p标签绑定3个点击事件),是不被允许的。那么,此时,出现了另一种事件处理程序,就是DOM2级的事件处理程序,在DOM2级当中,定义了两个基本方法,用于处理指定(即绑定)和删除事件处理程序的操作,分别是addEventListener()和removeEventListener

具体实例代码如下:

绑定多个同类型事件

DOM0级事件处理程序

addEventListener()和removeEventListener()中的第三个参数,表示的是在哪个事件阶段进行事件处理,如果是false,则指的是冒泡阶段;如果是true,则指的是捕获阶段。


事件类型

(1)单击事件onClick

  当用户单击鼠标按钮时,产生onClick事件。同时onClick指定的事件处理程序或代码将被调用执行。通常在下列基本对象中产生:

button(按钮对象)

checkbox(复选框)或(检查列表框)
radio (单选钮)
reset buttons(重要按钮)
submit buttons(提交按钮)

在onClick等号后,可以使用自己编写的函数作为事件处理程序,也可以使用JavaScript中内部的函数。还可以直接使用JavaScript的代码等。例:

(2)onChange改变事件

  当利用text或texturea元素输入字符值改变时发该事件,同时当在select表格项中一个选项状态改变后也会引发该事件。

(3)选中事件onSelect

  当Text或Textarea对象中的文字被加亮后,引发该事件。

(4)获得焦点事件onFocus

  当用户单击Text或textarea以及select对象时,产生该事件。此时该对象成为前台对象。

(5)失去焦点onBlur

  当text对象或textarea对象以及select对象不再拥有焦点、而退到后台时,引发该文件,他与onFocas事件是一个对应的关系。

(6)载入文件onLoad

  当文档载入时,产生该事件。onLoad一个作用就是在首次载入一个文档时检测cookie的值,并用一个变量为其赋值,使它可以被源代码使用。

(7)卸载文件onUnload

  当Web页面退出时引发onUnload事件,并可更新Cookie的状态。


这里写图片描述

事件流

事件流:描述的是从页面中接收事件的顺序。

① 事件捕获阶段

② 处于目标阶段

③ 事件冒泡阶段

IE与原来的NetScape(网景),对于事件流提出的是完全不同的顺序。IE团队提出的是事件冒泡流;NetScape的事件流是事件捕获流。

事件冒泡

事件冒泡:表示的是,事件开始的时候由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。

事件捕获

事件捕获:表示的是,事件开始的时候由最不具体的节点接收,然后逐级向下传播到最具体的节点。

这里写图片描述

来看一个实例:

    
tg

理解事件的基本概念

如果单击了p标签,那么,如果是事件冒泡流的事件流机制,则click事件将按照如下顺序进行执行:p —— div —— body —— html —— document。

如果采用捕获流的事件流机制,则click事件的执行顺序为:document —— html —— body —— div —— p

实例:

事件流
parent
child

① 点击parent,事件首先在document上然后parent捕获到事件,处于目标阶段然后event.target也等于parent,所以触发捕获事件

由于target与currentTarget相等了,所以认为到底了,开始冒泡,执行冒泡事件

② 点击child情况有所不同,事件由document传向parent执行事件,然后传向child最后开始冒泡,所以执行顺序各位一定要清晰

事件对象

事件对象:在触发DOM上的某个事件的时候,会产生一个事件对象event,而在这个对象当中会包含着所有与事件有关的信息。

所谓事件对象,是与特定对象相关,并且包含该事件详细信息的对象。

事件对象作为参数传递给事件处理程序(IE8之前通过window.event获得),所有事件对象都有事件类型type与事件目标target(IE8之前的srcElement我们不关注了)

各个事件的事件参数不一样,比如鼠标事件就会有相关坐标,包含和创建他的特定事件有关的属性和方法,触发的事件不一样,参数也不一样(比如鼠标事件就会有坐标信息),我们这里题几个较重要的

实例1

                
事件
理解事件的基本概念

bubbles

表明事件是否冒泡

cancelable

表明是否可以取消事件的默认行为

currentTarget

某事件处理程序当前正在处理的那个元素

defaultPrevented

为true表明已经调用了preventDefault(DOM3新增)

eventPhase

调用事件处理程序的阶段:1 捕获;2 处于阶段;3 冒泡阶段

这个属性的变化需要在断点中查看,不然你看到的总是0

target

事件目标(绑定事件那个dom)

trusted

true表明是系统的,false为开发人员自定义的(DOM3新增)

type

事件类型

view

与事件关联的抽象视图,发生事件的window对象

preventDefault

取消事件默认行为,cancelable是true时可以使用

stopPropagation

取消事件捕获/冒泡,bubbles为true才能使用

stopImmediatePropagation

取消事件进一步冒泡,并且组织任何事件处理程序被调用(DOM3新增)

在我们的事件处理内部,this与currentTarget相同

createEvent

可以在document对象上使用createEvent创建一个event对象

DOM3新增以下事件:  UIEvents  MouseEvents  MutationEvents,一般化dom变动  HTMLEvents一般dom事件

使用console.log打印出的结果。

实例某段代码

var type = 'click'; //要触发的事件类型  var bubbles = true; //事件是否可以冒泡 var cancelable = true; //事件是否可以阻止浏览器默认事件  var view = document.defaultView; //与事件关联的视图,该属性默认即可,不管  var detail = 0;  var screenX = 0;  var screenY = 0;  var clientX = 0;  var clientY = 0; var ctrlKey = false; //是否按下ctrl var altKey = false; //是否按下alt var shiftKey = false; var metaKey = false; var button = 0;//表示按下哪一个鼠标键 var relatedTarget = 0; //模拟mousemove或者out时候用到,与事件相关的对象 var event = document.createEvent('MouseEvents'); event.initMouseEvent(type, bubbles, cancelable, view, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);

我们就自己创建了一个event对象,然后可以传给我们自己创建的事件。

其中有两个信息,我们最为常用,分别是type和target。

type表示的是被触发事件的类型;

target表示的是事件的目标。

其他信息,如:

bubbles:表示事件是否冒泡cancelable:表示是否可以取消事件的默认行为currentTarget:表示事件处理程序当前正在处理事件的那个元素defaultPrevented:表示是否调用了preventDefault()detail:表示的是与事件相关的细节信息eventPhase:调用事件处理处理程序的阶段:1表示捕获阶段、2表示处于目标、3表示冒泡阶段

事件模拟

事件模拟是javascript事件机制中相当有用的功能,理解事件模拟与善用事件模拟是判别一个前端的重要依据,事件一般是由用户操作触发,其实javascript也是可以触发的,比较重要的是,javascript的触发事件还会冒泡。意思就是,javascript触发的事件与浏览器本身触发其实是一样的(并不完全一致)

如此,我们这里来通过键盘事件触发刚刚的点击事件吧,我们这里点击键盘便触发child的点击,看看他的表现如何

由于是键盘触发,便不具有相关参数了,我们可以捕捉event参数,这对我们队事件传输的理解有莫大的帮助:

我们这里先创建事件参数,然后给键盘注册事件,在点击键盘时候便触发child的点击事件

实例

无标题文档
parent
child

事件方面性能优化

谈一谈事件方面如何优化性能——事件委托和事件处理程序的移除

在JavaScript代码当中,添加到页面中的事件越多,页面的性能也就越差。导致这一问题的原因主要有:

每个函数都是对象,都会占用内存。内存中对象越多,性能也就越差。必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间。

为了进行页面的性能优化,因此我们会采用两种方法,就是上面提到的——事件委托和事件处理程序的移除。

事件委托

什么时候使用事件委托,其实,简单来说,当时一个页面事件处理程序比较多的时候,我们通常情况下会使用它。

事件委托主要利用了事件冒泡,只指定一个事件处理程序,就可以管理一个类型的所有事件。例如:我们为整个一个页面制定一个onclick事件处理程序,此时我们不必为页面中每个可点击的元素单独设置事件处理程序(onclick)。还是,看一个例子。

效果:点击不同的元素执行不同的操作。
不使用事件委托:

                
事件
1
2
3

不难看出,我们使用了5个事件侦听器,每设置一个就需要绑定一个。

使用事件委托:

                
事件-独行冰海
1
2
3

简要的总结一下所谓的事件委托:给元素的父级或者祖级,甚至页面绑定事件,然后利用事件冒泡的基本原理,通过事件目标对象进行检测,然后执行相关操作。其优势在于:

大大减少了事件处理程序的数量,在页面中设置事件处理程序的时间就更少了(DOM引用减少——也就是上面我们通过id去获取标签,所需要的查找操作以及DOM引用也就更少了)。document(注:上面的例子没有绑定在document上,而是绑定到了父级的div上,最为推荐的是绑定在document上)对象可以很快的访问到,而且可以在页面生命周期的任何时点上为它添加事件处理程序,并不需要等待DOMContentLoaded或者load事件。换句话说,只要可单击的元素在页面中呈现出来了,那么它就立刻具备了相应的功能。整个页面占用的内存空间会更少,从而提升了整体的性能。

移除事件处理程序

每当将一个事件处理程序指定给一个元素时,在运行中的浏览器代码与支持页面交互的JavaScript代码之间就会建立一个连接。连接数量也直接影响着页面的执行速度。所以,当内存中存在着过时的“空事件处理程序”的时候,就会造成Web应用程序的内存和性能问题。

那么什么时候会造成“空事件处理程序”的出现呢?

文档中元素存在事件,通过一些DOM节点操作(removeChild、replaceChild等方法),移除了这个元素,但是DOM节点的事件没有被移除。innerHTML去替换页面中的某一部分,页面中原来的部分存在事件,没有移除。页面卸载引起的事件处理程序在内存中的滞留。

解决方法:

合理利用事件委托;在执行相关操作的时候,先移除掉事件,再移除DOM节点;在页面卸载之前,先通过onunload事件移除掉所有事件处理程序。
你可能感兴趣的文章
VS2019 LINK Error 无法找到 mscoree.lib
查看>>
Verilog_MyHDL的使用
查看>>
VisualStudio2019的怪问题,在_Container_base12::_Orphan_all引发了异常: 读取访问权限冲突
查看>>
相机技术--摄像机720p、1080p、2mp、3mp、5mp;VGA, QHD, FHD, 2K,4K对应的分辨率分别是什么
查看>>
Visual Studio 的问题:unable to locate visual studio installer
查看>>
MCU_STM32F4XX_HAL_ADC_Start_DMA只能触发一次的问题
查看>>
Android四大组件之Service示例
查看>>
Android四大组件Service之前台进程(201807最新源码)
查看>>
实战Android:用AccessibilityService捕获volume按键
查看>>
实战Android:通过BroadcastReceiver监听Home,电源Power,和音量变化Volume键
查看>>
Android Studio错误:找不资源文件包 -- Cannot resolve symbol "R"
查看>>
实战Android:图片处理之ColorMatrix和Matrix实例
查看>>
Android Bitmap入门:getPixels的正确理解
查看>>
VS2017的怪问题--错误: 未能完成操作。未指定的错误
查看>>
Anaconda闪退的问题AttributeError: 'str' object has no attribute 'get'
查看>>
matplotlib中plot.show()不显示图片的问题:如何把backend=Agg配置为TkAgg
查看>>
ffmpeg截取视频片段命令优化
查看>>
我所理解的设计模式(C++实现)——访问者模式(Visitor Pattern)
查看>>
我所理解的设计模式(C++实现)——策略模式(Strategy Pattern)
查看>>
我所理解的设计模式(C++实现)——状态模式(State Pattern)
查看>>