第十七章:事件处理
事件处理概述
客户端JavaScript程序(浏览器)采用了异步事件驱动编程模型(我的理解是交互驱动)。当文档、 浏览器、元素或与之相关的对象发生某些有趣的事情时,Web浏览器就会产生事件(event)。如果JavaScript应用程序关注特定类型的事件,那么它可以注册当这类事件发生时要调用的一个或多个函数。这种风格并非Web编程独有,所有使用图形用户界面的应用程序都采用了它。
一些重要的定义:
1⃣️ 事件类型(event type):是一个用来说明发生什么类型事件的字符串。例如,“mouse-move”表示用户移动鼠标,“keydown”表示键盘上某个键被按下。事件类型只是一个字符串,有时候又称之为事件名字(event name);
2⃣️ 事件目标(event target) :是 发生事件或与之相关的对象 。 Window、 Document和Element对象是最常见的事件目标 。当然,AJAX中的XMLHttpRequest对象也是一个事件目标; 3⃣️ 事件处理程序(event handler) :是 处理或响应事件的函数,它也叫 事 件监听程序(event listener) 。应用程序通过指明事件类型和事件目标,在Web浏览器中注册它们的事件处理函数。 4⃣️ 事件对象(event object) :是 与特定事件相关且包含有关该事件详细信息的对象 。事件对象作为参数传递给事件处理函数(但是在IE8以及其之前版本中,全局变量event才是事件对象)。事件对象都有用来指定事件类型(event type)的type属性和指定事件目标(event target)的target属性 (但是在IE8以及其之前版本中,用的是srcElement而非target)。当然,不同类型的事件还会为其相关事件对象定义一些其他的独有属性。例如,鼠标事件的相关对象会包 含鼠标指针的坐标,而键盘事件的相关对象会包含按下的键和辅助键的详细信息。 5⃣️ 事件传播(event propagation) :如果在一个web页面上用鼠标点击一个元素a的某一子元素b时,应该先执行子元素b注册的事件处理程序还是先执行元素a注册的事件处理程序呢(假设元素a和它的子元素b都有注册事件处理程序)?
当一个事件发生时,它会先从浏览器顶级对象Window一路向下传递,一直传递到触发这个事件的那个元素,这也就是事件捕获(event capturing)过程。然而,一切并没有结束,事件又从这个元素一路向上传递到Window对象,这也就是事件冒泡(event bubble)过程(但是在IE8以及其之前版本中,事件模型并未定义捕获过程,只有冒泡过程)。
关于上面的问题,还得看元素a注册的事件处理程序是在捕获过程还是在冒泡过程了。事件的分类
1⃣️ 依赖于设备的输入事件 :mousedown/mouseover/keydown等; 2⃣️ 独立于设备的输入事件 :click(指激活了链接、按钮或其他文档元素,可用鼠标也可用键盘回车键等) 3⃣️ 用户界面事件 :change/focuse/submit(用户点击表单中提交后触发); 4⃣️ 状态变化事件 :load/readystatechange; 5⃣️ 特定API事件 :HTML5中定义的包括dragstart/dragenter以及 6⃣️ 计算器和错误处理程序 ;传统事件类型
1⃣️ 表单事件 当提交和重置表单时, submit 和 reset 事件,当用户和类按钮表单元素交互时,它们会发生 click 事件,用户通过输入文字、选择选项或选择复选框来改变相应表单元素状态时,这些元素会发生 change 事件(对于文本域只有用户和表单完成交互并通过Tab键或单击方式移动焦点时才会触发),表单某元素得到或失去焦点时触发 focus 和 blur 事件; 2⃣️ Window事件 Window事件指: 事件发生于浏览器窗口本身而非窗口中显示的任何特定文档相关内容。 load事件 :当文档和其所有外部资源完全加载并显示给用户时就会触发它。 unload事件 :当用户离开当前文档转向其他文档时会触发它。 onerror事件 :当Javascript出错时会触发。 resize 和 scroll 事件 :用户调整浏览器窗口大小或滚动它时会触发。 3⃣️ 鼠标事件 鼠标事件在鼠标指针所对应的最深嵌套元素上触发,但它们会冒泡直到文档最顶层。 clientX 和 clientY 属性指定了鼠标在窗口坐标中的位置。 button 和 which 属性指定了按下的鼠标键是哪个。 当键盘辅助键按下时,对应的属性 altKey/ctrlKey/metaKey 和 shifKey 会设置为true。对于click事件, detail 属性指定了其是单击、双击还是三击。 其他鼠标事件的触发:- mousemove事件:用户每次移动或拖动鼠标时触发 (发生很频繁)。
JavaScript中常用的事件类型
上面笔记中提到的传统事件类型都是web应用中最常用的,它们已经存在了很长时间并得到了广泛的支持。下面综合一下如今几种常用的事件类型:1⃣️ UI事件
UI事件指的是那些 不一定与用户操作有关 的事件。DOM规范中向后兼容。 UI事件包含:- load:当页面加载后在window上面触发,当所有框架加载完成后在框架上触发,当图像加载完成后在
元素上面触发。
- unload:当页面卸载后在window上面触发。
- abort:当用户停止下载过程时,如果嵌入的内容没有加载完,则在
- error:当发生JavaScript错误时在window上面触发。
- select:当用户选择文本框(input或textarea)或一个字符串时触发。
- resize:当窗口或框架大小变化时在window上面触发。
- scroll:当用户滚动滚动条的元素中的内容时,在元素上触发。
EventUtil.addHandler(window, "load", function (event) {alert("load");
}); //load事件 第二种方法就是在HTML的中定义:
建议尽可能使用JavaScript代码来定义load事件。
unload事件
只要文档被卸载后就会触发,当用户从一个页面切换到另一个页面就会触发,一般用于清除引用,避免内存泄露使用。定义unload事件也有两种方式,与定义load事件一样。 resize事件 resize事件是当窗口或框架的尺寸大小发生变化时触发,这个事件是在window上触发的。建议使用JavaScript定义onresize事件处理程序。也有两种定义方法。EventUtil.addHandler(window, "resize", function (event) {alert("resize");
}); /resize事件 该事件会在窗口大小不断变化时重复触发,因此建议代码简单点。 scroll事件 定义方法与load、unload、resize一样,也是两种即: 在HTML中定义或用JavaScript定义 ,建议用JavaScript定义。scroll是在window对象上发生的,但它实际上是反应了相应元素的变化。这个事件会在文档被滚动期间重复被触发,所以应当尽量保持事件处理程序的代码简单。 2⃣️ 焦点事件
焦点会在页面得到焦点或失去焦点时触发 。- focus,在得到焦点的元素上触发,这个事件不会冒泡。
- focusIn,在得到焦点的元素上触发 ,这个事件会冒泡。
- DOMFocusIn,在得到焦点的元素上触发,这个事件会冒泡。
- DOMFocusOut,在失去焦点的元素上触发。
- blur,在失去焦点的元素上触发,这个事件不会冒泡。
- focusout,在失去焦点的元素上触发,这个事件会冒泡。
let input1 = document.getElementById("input1");
input1.onfocus = function (event) {alert("hi"); //hi
}; 当input元素失去焦点时,会触发blur事件。 let input1 = document.getElementById("input1");
input1.onblur = function (event) {alert("失去焦点"); //失去焦点
}; 3⃣️ 鼠标与滚轮事件
常见的鼠标事件:- click:鼠标单击事件,当单击鼠标(一般为左键)或按下回车键时,会触发事件。
- dbclick:鼠标双击事件,当双击鼠标时,会触发事件。
- mousedown:当任意按下鼠标键时,会触发事件。
- mouseup:当释放鼠标铵键时,会触发事件。
- mouseover:当鼠标移动进到当前元素的区域就会触发事件。
- mouseout:当鼠标移出当前元素的区域就会触发事件。
- mousemove:当鼠标在当前元素区域内不断移动时,会重复触发事件。
let input1 = document.getElementById("input1");
input1.onmousedown = function (event) {alert("按下鼠标按键");
}; 当释放鼠标按键时:
let input1 = document.getElementById("input1");
input1.onmouseup = function (event) {alert("释放鼠标按键");
}; 当单击鼠标按键时:
let input1 = document.getElementById("input1");
input1.onclick = function (event) {alert("点击鼠标按键");
}; 当双击鼠标按键时:
let input1 = document.getElementById("input1");
input1.ondbclick = function (event) {alert("双击鼠标按键");
}; 客户区坐标位置 鼠标事件都是在浏览器视口中特定位置发生的,这些位置信息保存在对象的 clientX和clientY属性中,这两个属性分别表示鼠标在视口中水平位置和垂直位置 。 注:这两个值不包括页面滚动的距离,也就是说,这两个值不包括鼠标在页面中的位置,只是表示在视口中的某位置发生了事件。
JavaScript
页面坐标位置 客户区坐标位置只是表示鼠标在视口的某位置发生了事件,而想要表示鼠标在页面中的某个位置发生了事件,则用 pageX和pageY表示鼠标在页面中的水平位置和垂直位置 。
JavaScript
视口位置与页面位置的区别: 视口位置不包括页面滚动的距离,也就是说当页面出现有滚动条时,即使在视口的同一位置点击相同的元素,视口位置与页面位置所返回的值是不同的。 视口位置是从视口区的顶端即最后一工具栏下和浏览器左端开始计算的,即使水平方向和垂直方向上出现了滚动条,也是从视口的顶端和浏览器的左边作为起始坐标计算的。而页面位置则从页面的最顶端和页面的最左边开始计算的,即使有了滚动条也是。 屏幕坐标位置 鼠标除了有相对于浏览器窗口的位置,还有相对于屏幕的位置,即 screenX与screenY 。
JavaScript
即使鼠标在同一点击事件,clientY与screenY的值是不同的,screenY的值大一些,这是因为浏览器的菜单栏与工具栏要占一定的空间。
修改键 鼠标事件主要是由鼠标触发的,但有时有些按键也会影响到鼠标事件的操作,这些键叫做 修改键 。修改键有: Shift、Ctrl、Alt和Meta (windows下是Windows键,苹果下是Cmd键),DOM为此定义了四个属性,表示这四个键的状态: shiftKey、CtrlKey、altKey和metaKey 。如果在鼠标触发事件的同时,也按下了这四个修改中的其中一个或多个,其状态属性返回true。
JavaScript
鼠标的按钮 在鼠标事件中,有 mousedown和mouseup 两个事件,分别表示鼠标键被按下和鼠标键被释放。这两个事件的event对象有一个叫 botton 的属性,该属性记录了触发mousedown和mouseup事件时,用户所按下的鼠标的按键状态。 我们知道,鼠标主要有三个按键,分别是 主按键、中间按键、次按键 。botton属性所记录的就是这三个按键的状态。 在DOM的botton属性中,当botton返回0时,表示用户按下的是鼠标的主按键,返回1时,表示用户按下的是鼠标的中间按键(也就滑轮),返回2时,表示用户按下的是鼠标的次按键。 注:鼠标默认的按键是最左边的为主按键,中间的滑轮为中间按键,最右边的为次按键,当然,用户可以自定义设置这三个按键。
JavaScript
鼠标datail属性 在"DOM2级事件"中Event对象还提供了一个叫 detail 的属性,该属性表示事件的更多信息。比如:鼠标事件中,该属性包含一个数值,表示发生了多少次单击,在同一个元素上, 连续发生一次mousedown和一次mouseup算作一次单击 ,detail的值是从1开始计数,每次单击发生后数值递增。如果鼠标在mousedown和mouseup之间移动了位置,则datail重置为0。 注:如果是 连续地单击鼠标 ,detail值会递增并显示,表示此次单击了多 次,但如果是 间断地单击鼠标 ,则datail的值还是1,表示为此次只单击了一 次。
JavaScript
鼠标滑动事件 当用户通过鼠标滑轮(滚轮)与页面交互、上下滚动页面时,会触发一个叫 mousewheel 的事件即 鼠标滑动事件 。该事件的event对象不仅包含了鼠标事件的所有信息,还包含一个叫做 wheelDelta 属性,当鼠标滑轮滚动时,该属性返回120的倍数。当向前滑动时(即页面向下滑动),wheelDelta属性返回-120的倍数,当向后滑动时(即页面向上滑动),wheelDelta属性返回+120的倍数。
JavaScript
4⃣️ 键盘与文本事件
用户在使用键盘时会触发键盘事件。常用的键盘事件有3种:- keydown:按下键盘上的任意按键会触发事件,如果按住按键不放,则会重复触发事件。
- keyup:当释放键盘按键时会触发事件。
- keypress:当用户按住键盘上的字符键时会触发事件,如果按住不放,则会重复触发事件。
JavaScript
键码
当触发keydown和keyup事件时,其event对象有个叫做 keyCode 的属性,其包含了用户所按下的按键的字符键码。例如:字符“q”对应的键码为81,字符"w"对应的键码是87。 注: keyCode属性不会区分字符大小写状态的 ,例如:不管是大写A还是小写a均返回65。
JavaScript



JavaScript
DOM3级变化 DOM3级中,新增了两个属性: key和char ,这两个属性取代了charCode属性。 key属性返回的是一个字符串,即用当用户所按键是字符时,会返回相应的字符 ,如"k"、“w”等,而 当用户所按为非字符按键时,该属性会返回相应的键名 ,如“shift”, "ctrl"等。 char属性 与key属性相似, 当用户按下字符按键时,会返回相应的字符 ,但 当用户按下的是非字符按键时,该属性会返回null 。 由于存在跨浏览器问题,还是不建议使用char和key属性。 DOM3中的location属性,该属性返回一个数值,表示用户所按下的按键处于键盘的什么位置。返回0表示在默认键盘位置,返回1表示在左侧位置(即左侧的shift),返回2表示在右侧位置(即右侧的shift),返回3表示数字小键盘,返回4表示移动设备键盘,返回5表示手柄。火狐和谷歌支持的是keyLocaltion属性。 textInput事件 当用户在可编辑区域输入字符时,会触发该事件。 textInput事件与keypress事件的区别: - textInput事件只有在可输入区域才能触发,而keypress事件就是只要任何获取焦点的元素就会触发该事件。
- 只有输入实际的字符才能触发textInput事件,而keypress事件,只要按下是否能影响文本显示的按键时就能触发。
Version:0.9 StartHTML:0000000105 EndHTML:0000031901 StartFragment:0000000141 EndFragment:0000031861
5⃣️ 复合事件
复合事件是DOM3新增的一类事件,用于处理输入的IME的输入序列。 复合事件可以让用户输入物理键盘上没有的字符。6⃣️ 变动事件
变动事件:DOM中某一部分发生变化时就会触发 。如删除节点、插入节点等操作。DOM2级中的变动事件如下:- DOMSubtreeModified:在DOM结构中发生任何变化时触发。这个事件在其它事件触发后都会触发。
- DOMNodeRemoved:在节点从其父节点中移出时触发。(删除节点时)
- DOMNodeInserted:在一个节点作为另一个节点的子节点插入时触发。(插入节点)
- DOMNodeInsertedIntoDocument:在一个节点直接被插入到文档中或通过DOM子树结构插入到文档中时触发。
- DOMNodeRemovedFromDocument:在一个节点直接从文档中移出或通过DOM子树结构移出时触发。
变动事件之删除节点操作 - li 1
- li 2
- li 3
- li 4
可以看出当要删除- 节点时会经过以下的操作步骤:
- 首先在
- 元素上触发DOMNodeRemoved事件,该事件的目标就是当
- ,该事件的Event对象的relatedNode引用的是其父节点即
- 接着,在
- 元素上触发DOMNodeRemovedFromDocument事件,
- 元素本身,并且Event对象不包含其它信息了。
- 再接着,在
- 元素的子节点(当然要看被删除节点是否有子节点,如
- 元素上也触发
DOMNodeRemovedFromDocument事件,这次该事件的目标就是"#text",因为- 元素包含的是文本内容。
- 随着在其父节点上(document.body)上触发DOMSubtreeModified事件,该事件的目标就是document.body。
- 最后,经过以上事件处理程序的操作,将
- 元素节点从其父元素中删
- 首先会触发DOMNodeInsered事件,该事件的目标是被插入的节点(event.target),而event.relatedNode包含一个父节点的引用。在这个事件触发时,该节点已经被插入到文档中了。这个事件有冒泡,所以可以在DOM的任何层次上处理(也就是说,可以在DOM结构的任何层次上创建该事件的处理程序)。
- 接着会在新插入的节点上触发DOMNoeInseredIntoDocument事件。该事件不会冒泡,所有需在该节点被插入之前为它添加事件处理程序(也就是说只能新插入的节点上创建处理程序),该事件的目标就是这个新插入的节点,除此之外Event对象不包含其它事件信息。
- 最后在新插入的节点的父节点上触发DOMSubtreeModefied事件,该事件不包含任何有关事件的信息。
- 元素节点新插入一个子节点。注:该新节点需要新创建。
变动事件之删除节点操作 - li 1
- li 2
- li 3
- li 4
Version:0.9 StartHTML:0000000105 EndHTML:0000022881 StartFragment:0000000141 EndFragment:0000022841
7⃣️ TML5事件
DOM规范没有涵盖浏览器支持的所有事件,HTML5列出了浏览器的支持的所有事件,下面是得到浏览器完美支持的事件: contextmenu事件 默认的上下文菜单栏:当点击鼠标右键时,会出现一个默认的菜单栏。为了实现自定义的上下文菜单,开发人员遇见的主要问题是:如何确定要显示的菜单,如何隐藏和操作菜单。于是contextmenu事件出现了。 contextmenu事件属于鼠标事件,一般为鼠标右键事件,它是冒泡的 ,所以可以为document指定一个事件处理程序。该事件的目标是被用户操作的元素。为了实现自定义的上下文菜单,首先是阻止鼠标右键的默认行为(即点击鼠标右键弹出默认菜单栏)。contextmenu事件属于鼠标事件,那么就可以通过event对象得到鼠标的位置,恰好自定义菜单出现的位置也是鼠标单击的位置。通常使用contextmenu事件来显示自定义的菜单栏,而通过鼠标的click事件来隐藏该菜单栏。 比如:通过按鼠标右键弹出自定义菜单栏来选择上下面、首页、尾页等操作。
contextmenu事件 文章内容- 首页
- 上一页
- 下一页
- 尾页
beforeunload事件 当卸载页面、或者重新刷新页面时,可能我们没有保存数据,刷新之后,数据就会消失。如果给winsow添加一个叫 beforeunload() 的事件处理程序,那么当我们要重新刷新页面时,页面会弹出警告框,要我们确认是否要刷新这个页面,这是一个友好的提示: window.onbeforeunload = function (e) {let message = "确定要离开页面吗";return message;
}; DOMContentLoaded事件 window的load事件会在页面加载完成之后触发,但这个过程可能会因为要加载的资源大多而等的时间较长。 DOMContentLoaded事件在形成完整的DOM结构之后就会触发,而不必等到图像、JavaScript资源、CSS资源加载完毕之后才触发 。这样用户就可以早点与浏览器交互。可以为document或window添加处理程序,但目标还是document。 window.addEventListenter("DOMContentLoaded", function () {alert("用户早点与浏览器交互");
}); readystatechange事件 该事件的目的是提供与文档或元素加载状态有关的信息 。readystatechange事件的Event对象有个readyState属性,保存着状态值。状态值有5个: - uninitialized(未初始化):对象存在但未初始化。
- loading:对象正在加载数据。
- loaded:对象已经加载完数据。
- interactive:可以操作对象了,但未完全加载。
- compelete:对象已经加载完毕。
8⃣️ 拖放事件
在HTML5之前,如果要实现拖放效果,一般会使用 mousedown、mousemove和mouseup 三个事件进行组合来模拟出拖拽效果,比较麻烦。 HTML5为所有的HTML元素规定了一个 draggable 属性,表示元素是否允许拖动。要想让其他元素也能被拖动,可以设置这个属性为true。 创建一个可拖放对象 如果想要拖动某个元素,需要设置元素的 draggable 属性为 true。![]()
给 dragstart 设置一个事件监听器存储拖放数据和效果。 document.getElementById("dragImg").addEventListener("dragstart",function(event) {event.dataTransfer.setData("Text",ev.target.id);
}, false); 放置对象 假设放置对象的DOM为: dragenter事件,用来确定放置目标是否接受放置。如果放置被接受,那么这个事件必须取消。 document.getElementById("dragTarget").addEventListener("dragenter",function(event) {// 阻止浏览器默认事件event.preventDefault();
}, false); dragover事件,用来确定给用户显示怎样的反馈信息。如果这个事件被取消,反馈信息(通常就是光标)就会基于 dropEffect 属性的值更新。 document.getElementById("dragTarget").addEventListener("dragover",function(event) {// 阻止浏览器默认事件event.preventDefault();
}, false); 最后是drop事件 ,允许放置对象。 document.getElementById("dragTarget").addEventListener("drop",function(event) {event.preventDefault();let data=event.dataTransfer.getData("Text");event.target.appendChild(document.getElementById(data));
}, false); 例子:
please drop the picture to the box!
拖放的相关事件
| 事件 | 产生事件的元素 | 描述 |
|---|---|---|
| dragstart | 被拖放的元素 | 开始拖放操作 |
| drag | 被拖放的元素 | 拖放过程中 |
| dragenter | 拖放过程中鼠标经过的元素 | 被拖放元素开始进入本元素范围内 |
| dragover | 拖放过程中鼠标经过的元素 | 被拖放元素正在本元素范围内移动 |
| dragleave | 拖放过程中鼠标经过的元素 | 被拖放元素离开本元素范围 |
| drop | 拖放的目标元素 | 有其他元素被拖放到本元素中 |
| dragend | 拖放的目标元素 | 拖放操作结束 |
DataTransfer属性
| 属性 | 描述 |
|---|---|
| dropEffect | 表示拖放操作的视觉效果,允许对其进行值的设定。该效果必须 在用effectAllowed属性指定的允许的视觉效果范围内,允许指 定的值有:none、copy、link、move。 |
| effectAllowed | 用来指定当元素被拖放时所允许的视觉效果。可以指定的值有: none、copy、copyLink、copyMove、link、linkMove、all、 uninitialize。 |
| files | 返回表示被拖拽文件的 FileList。 |
| types | 存入数据的MIME类型。如果任意文件被拖拽,那么其中一个类 型将会是字符串”Files”。 |
DataTransfer方法
| 方法 | 描述 |
|---|---|
| void setData(DOMString format, DOMString data) | 向DataTransfer对象存入数据。 |
| DOMString getData(DOMString data) | 读取DataTransfer对象中的数据。 |
| void clearData(DOMString format) | 清除DataTransfer对象中的数据。如 果省略参数format,则清除全部数 据。 |
| void setDragImage(Element image, long x, long y) | 用img元素来设置拖放图标。 |
注册事件处理程序
1⃣️ 设置JavaScript对象属性为事件处理程序 可以通过设置某一事件目标的事件处理程序属性来为其注册相应的事件处理程序 。事件处理程序属性名字由 “on”后面跟着事件名组成 ,例如:onclick、onmouseover。
test div1div2div3
- 因为JavaScript是严格区分大小写的,所以,这种形式下属性名只能按规定小写;
- 若给同一元素对象写多个onclick事件处理属性,后面写的会覆盖前面的(ps:这就是在修改一个对象属性的值,属性的值是唯一确定的);
- 这种形式也是在事件冒泡过程中注册事件处理程序的。
test div1div2div3
- 因为HTML里面不区分大小写,所以这里事件处理程序属性名大写、小写、大小混写均可,属性值就是相应事件处理程序的JavaScript代码;
- 若给同一元素写多个onclick事件处理属性,浏览器只执行第一个onclick里面的代码,后面的会被忽略;
- 这种形式是在事件冒泡过程中注册事件处理程序的。
test div1div2div3
- addEventListener()第三个参数可以忽略;
- 通过addEventListener()方法给同一对象注册多个同类型的事件,并不会发生忽略或覆盖,而是会按顺序依次执行;
div1.addEventListener('click', div1BubbleFun, false);
div1.removeEventListener('click', div1BubbleFun, false);function div1BubbleFun(){console.log('div1-bubble');};
4⃣️ attachEvent()
IE8以及其之前版本的浏览器并不支持addEventListener()和removeEventListener()。相应的,IE定义了类似的方法 attachEvent()和detachEvent() 。因为IE8以及其之前版本浏览器也不支持事件捕获,所以attachEvent()并不能注册捕获过程中的事件处理函数,因此 attachEvent()和
detachEvent()要求只有两个参数:事件类型和事件处理函数。而且,它们的第一个参数使用了带“on”前缀的事件处理程序属性名 。
let div1 = document.getElementById('div1');
div1.attachEvent('onclick', div1BubbleFun);
function div1BubbleFun(){console.log('div1-bubble');
}
相应的,从对象上删除事件处理程序函数使用detachEvent()。
div1.detachEvent('onclick', div1BubbleFun);
事件处理程序的调用
1⃣️ 事件处理程序的参数 通常事件对象作为参数传递给事件处理函数,但IE8以及其之前版本的浏览器中全局变量event才是事件对象。所以,我们在写相关代码时应该 注意兼容性问题 。 给页面上id为div1的元素添加点击事件,当点击该元素时在控制台输出事件类型和被点击元素本身:
test div1
2⃣️ 事件处理程序的运行环境
关于事件处理程序的运行环境,要注意事件处理程序中 调用上下文(this值) 的指向问题。
- 事件处理程序中this指向这个元素本身:
test div1
- 在中 添加如下script代码,代码中的this也指向元素本身,但是会覆盖前面注册的事件处理程序:
- 在标签中继续添加如下代码,代码中的this同样指向元素本身,并且不会覆盖前面注册的事件处理程序:
div1.addEventListener('click', function(){console.log('div1.addEventListener:');console.log(this);}, false);
- 在标签中添加如下代码,代码中的this指向的则是全局对象window,并且该方法也不会覆盖前面注册的事件处理程序:
div1.attachEvent('onclick', function(){console.log('div1.attachEvent:');console.log(this === window);
});
3⃣️ 事件处理程序的调用顺序
多个事件处理程序调用规则如下:
- 通过HTML属性注册的处理程序和通过设置对象属性的处理程序一直优先调用;
- 使用addEventListener()注册的处理程序按照它们的注册顺序依次调用;
- 使用attachEvent()注册的处理程序可能按照任何顺序调用,所以代码不应该依赖于调用顺序;
function cancelHandler(event){let event = event || window.event;if(event.preventDefault){event.preventDefault();}if(event.returnValue){event.returnValue = false;}return false;
}
取消事件传播
在支持addEventListener()的浏览器中,可以调用事件对象的一个 stopPropagation() 方法阻止事件的继续传播,它能工作在事件传播期间的任何阶段(捕获期阶段、事件目标本身、冒泡阶段)
但是在IE8以及其之前版本的浏览器中并不支持stopPropagation()方法,而且这些浏览器也不支持事件传播的捕获阶段,相应的,IE事件对象有一个 cancelBubble 属性,设置这个属性为true能阻止事件进一步传播(即阻止其冒泡)。
阻止发生在div3区域的点击事件冒泡到div2和div1:
test div1div2div3
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
