本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2022-05-21
JavaScript
与HTML
之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。可以使用侦听器(或处理程序)来预订事件,以便事件发生时执行相应的代码(属于观察者模式),在DOM
元素上注册事件处理程序就是订阅,当事件被触发的时候,DOM
元素便会向订阅者发布这个消息。当然我们还可以随意增加或者删除订阅者,增加任何订阅者都不会影响发布者代码的编写。
事件流描述的是从页面中接收事件的顺序,分为事件冒泡和事件捕获,事件冒泡就是targetElement -> body -> document
,事件捕获就是document -> body -> targetElement
。
DOM2级事件
规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,为截获事件提供了机会。然后是实际的目标接收到事件。最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应。document -> body ->targetElement -> body -> document
某个元素支持的每种事件,都可以使用一个与相应事件处理程序同名的HTML
属性来指定。属性值可以是一个js语句
字符串,例如:alert('hello wrold')
;也可以是一个定义在全局作用域下的函数调用,在事件被触发时,会执行相关代码。由此可知属性值是指定的函数代码,如果将这个属性值设置为null
,也可以移除该事件。
<input type="button" name="clickBtn" value="Echo Username" onclick="show()">
<input type="button" name="clickBtn1" value="test" onclick="alert(this.name)">
<!-- 第二个按钮被点击会弹出"clickBtn1" 在html定义的事件函数的this指向当前元素 -->
<script>
function show() {
console.log(this); // window
}
</script>
在form
中 input
的name
属性,会在form
中生成一个同名指针指向对应的input
。在form
表单元素中,事件函数的作用域相当于有document
、form
、 本身元素,可以像访问局部变量一样访问这些作用域中的属性 ,所以可以直接访问到username.value
相当于form.username.value
<form method="post" id="form1">
<input type="text" name="username" value="">
<input type="button" name="clickBtn" value="Echo Username" onclick="alert(username.value)">
</form>
<script>
var form1 = document.getElementById('form1')
console.log(form1);
console.log(form1.username); // 打印出name为username的input元素
console.log(form1.clickBtn.value); // Echo Username
</script>
使用DOM0级方法
指定的事件处理程序被认为是元素的方法。因此,这时候的事件处理程序是在元素的作用域中运行;换句话说,程序中的this
引用当前元素。
<input type="button" id="btn1" name="clickBtn" value="Echo Username">
<script>
var oBtn = document.getElementById('btn1')
oBtn.onclick = function(){
console.log(this.name) // 'clickBtn'
// 使用JavaScript 指定事件处理程序 this指向注册事件的元素
}
btn.onclick = null; //删除事件处理程序
</script>
addEventListener()
和removeEventListener()
。所有DOM
节点中都包含这两个方法,并且它们都接受3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true
,表示在捕获阶段调用事件处理程序;如果是false
,表示在冒泡阶段调用事件处理程序。
var btn = document.getElementById("myBtn");
btn.addEventListener("click", function(){
alert(this.id);
}, false);
btn.addEventListener("click", function(){
alert("Hello world!");
}, false);
使用DOM2 级方法
添加事件处理程序的主要好处是可以添加多个事件处理程序。不会被覆盖,会根据添加的顺序相继执行;removeEventListener()
来移除事件处理程序,移除时传入的参数与添加处理程序时使用的参数相同。这也意味着通过addEventListener()
添加的匿名函数将无法移除。
attachEvent()
和detachEvent()
这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数,因为IE8及更早的版本只支持事件冒泡。第一个参数事件处理程序名称字符串是需要加"on"
的,例如"onclick"
。也可以用来为一个元素添加多个事件处理程序,但是不是以添加它们的顺序执行,而是以相反的顺序被触发。attachEvent()
添加的匿名函数也不能使用detachEvent()
移除。
var EventUtil = {
addHandler: function(element, type, handler){
if (element.addEventListener){
element.addEventListener(type, handler, false);
} else if (element.attachEvent){
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
removeHandler: function(element, type, handler){
if (element.removeEventListener){
element.removeEventListener(type, handler, false);
} else if (element.detachEvent){
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
}
};
EventUtil.addHandler(btn, "click", handler);
EventUtil.removeHandler(btn, "click", handler);
在触发DOM
上的某个事件时,会产生一个事件对象event
,这个对象中包含着所有与事件有关的信息。包括导致事件的元素、事件的类型以及其他与特定事件相关的信息。
bubbles
:Boolean
类型,表明事件是否冒泡。cancelable
: Boolean
类型,表明是否可以取消事件的默认行为。currentTarget
:Element
类型,其事件处理程序当前正在处理事件的那个元素。preventDefault()
:取消事件的默认行为。如果cancelable
是true
,则可以使用这个方法defaultPrevented
:Boolean
类型,为true
表示已经调用了preventDefault()
;DOM3
新增stopPropagation()
:取消事件的进一步捕获或冒泡。如果bubbles
为true
,则可以使用这个方法。stopImmediatePropagation()
:取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用;DOM3
新增target
:Element
类型,事件的目标。type
:String
类型,被触发的事件的类型eventPhase
:调用事件处理程序的阶段:1表示捕获阶段,2表示“处于目标”,3表示冒泡阶段事件处理程序中的this
和currentTarget
,均指向注册事件的那个元素。而target
则指向的是事件目标,即事件在哪个元素上被触发。如果注册事件的元素和触发事件的元素则三个值相等。
如果你想阻止链接导航这一默认行为,那么可以通过preventDefault()
取消它。
var link = document.getElementById("myLink");
link.onclick = function(e){
e.preventDefault();
};
如果你想停止事件在DOM
层次中的传播,即取消进一步的事件捕获或冒泡。
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
alert("Clicked");
event.stopPropagation();
};
document.body.onclick = function(event){
alert("Body clicked"); // 将不会执行。
};
User Interface
(用户界面)事件,指的是那些不一定与用户操作有关的事件。
onload
:当页面完全加载后(包括所有图像、JavaScript
文件、CSS
文件等外部资源)在window
上面触发,当图像加载完毕时在<img>
元素上面触发,或者当嵌入的内容加载完毕时在<script>|<link>
元素上面触发。
我们如果想向DOM
中添加一个新元素,必须确定页面已经加载完毕——如果在页面加载前操作DOM
会导致错误。新图像元素不一定要被添加到文档后才开始下载,只要设置了src
属性就会开始下载。与图像不同,只有在设置了<script>
元素的src
属性并将该元素添加到文档后,才会开始下载JavaScript
文件。
除IE8及更早版本外,都支持<script>
的onload
事件;IE 和Opera 支持<link>
元素上的onload
事件。
onunload
事件在文档被完全卸载后触发。只要用户从一个页面切换到另一个页面,就会发生unload
事件。用的最多的情况是清除引用,以避免内存泄漏。可以注册在window
对象上,也可以在为<body>
元素添加onunload
属性来指定事件处理程序。
在用户停止下载过程时,如果嵌入的内容没有加载完,则在<script>|<link>
元素上面触发。
当发生JavaScript
错误时在window
上面触发,当无法加载图像时在<img>
元素上面触发,当无法加载嵌入内容时在<script>|<link>
元素上面触发,或者当有一或多个框架无法加载时在框架集上面触发。
当用户选择文本框(<input>
或<texterea>
)中的一或多个字符时触发。
onresize
:当窗口或框架的大小变化时在window
或框架上面触发。
onscroll
:当用户滚动带滚动条的元素中的内容时,在该元素上面触发。<body>
元素中包含所加载页面的滚动条。可以通过document.documentElement / document.body
的scrollLeft
和scrollTop
属性 来监控到这一变化。
resize
和scroll
事件也会在窗口变化/文档被滚动期间重复被触发,所以有必要尽量保持这两个事件处理程序的代码简单。
焦点事件会在页面元素获得或失去焦点时触发。利用这些事件并与document.hasFocus()
方法及document.activeElement
属性配合,可以知晓用户在页面上的行踪。
onblur
:在元素失去焦点时触发。这个事件不会冒泡;onfocus
:在元素获得焦点时触发。这个事件不会冒泡;onclick
:在用户单击主鼠标按钮(一般是左边的按钮)或者按下回车键时触发。这一点对确保易访问性很重要,意味onclick
事件处理程序既可以通过键盘也可以通过鼠标执行。
ondblclick
:在用户双击主鼠标按钮(一般是左边的按钮)时触发。
onmousedown
:在用户按下了任意鼠标按钮时触发。不能通过键盘触发这个事件。
onmouseenter
:在鼠标光标从元素外部首次移动到元素范围之内时触发。这个事件不冒泡,而且在光标移动到后代元素上不会触发。
onmouseleave
:在位于元素上方的鼠标光标移动到元素范围之外时触发。这个事件不冒泡,而且在光标移动到后代元素上不会触发。
onmousemove
:当鼠标指针在元素内部移动时重复地触发。不能通过键盘触发这个事件。
onmouseout
:在鼠标指针位于目标元素上方,然后用户将其移入另一个元素时在目标元素触发。移入目标元素外部或者是移入目标元素的子元素也会触发。不能通过键盘触发这个事件。
onmouseover
:在鼠标指针位于目标元素外部或者目标元素的子元素上,然后用户将其移入目标元素时触发。不能通过键盘触发这个事件。
onmouseup
:在用户释放鼠标按钮时触发。不能通过键盘触发这个事件。
onmousewheel
:在用户滚动鼠标滚轮时触发。
页面上的所有元素都支持鼠标事件。除了mouseenter
和mouseleave
,所有鼠标事件都会冒泡,也可以被取消,而取消鼠标事件将会影响浏览器的默认行为。
只有在同一个元素上相继触发mousedown
和mouseup
事件,才会触发click
事件;如果mousedown
或mouseup
中的一个被取消,就不会触发click 事件。顺序是:mousedown->mouseup->click->mousedown->mouseup->click->dblclick
鼠标事件都是在浏览器视口中的特定位置上发生的,会有相应的位置信息保存在事件对象中:
位置信息
e.clientX
:鼠标位置在视口中的水平坐标。e.clientX
:鼠标位置在视口中的水平坐标。e.pageX
:鼠标位置在文档中的水平坐标。如果页面向右滚动了,这个值大于e.clientX
,否则相等。e.pageY
:鼠标位置在文档中的垂直坐标。如果页面向下滚动了,这个值大于e.clientY
,否则相等。e.screenX
:鼠标位置在整个电脑屏幕中的水平坐标。e.screenY
:鼠标位置在整个电脑屏幕中的垂直坐标。修改键
e.shiftKey
:Boolean
类型,表示鼠标被按下时,是否shift
键也被按下了。e.ctrlKey
:Boolean
类型,表示鼠标被按下时,是否ctrl
键也被按下了。e.altKey
:Boolean
类型,表示鼠标被按下时,是否alt
键也被按下了。e.metaKey
:Boolean
类型,表示鼠标被按下时,是否meta
键也被按下了。即Window系统的Windows
键和Mac系统的Cmd
键。相关元素
e.relatedTarget
在发生mouseover
和mouseout
事件时,还会涉及更多的元素。这两个事件都会涉及把鼠标指针从一个元素的边界之内移动到另一个元素的边界之内。对mouseover
事件而言,事件的主目标是获得光标的元素,而相关元素就是那个失去光标的元素。类似地,对mouseout
事件而言,事件的主目标是失去光标的元素,而相关元素则是获得光标的元素。DOM
通过event
对象的relatedTarget
属性提供了相关元素的信息。这个属性只对于mouseover
和mouseout
事件才包含值。在其他鼠标事件触发时,这个值是null
IE8及之前版本不支持relatedTarget
属性,在mouseover
事件触发时,IE 的fromElement
属性中保存了相关元素;在mouseout
事件触发时,IE 的toElement
属性中保存着相关元素。
鼠标按钮
e.button
该属性可能有如下3 个值:0 表示主鼠标按钮(一般是左键),1 表示中间的鼠标按钮(鼠标滚轮按钮),2 表示次鼠标按钮(一般是右键)。在使用onmouseup
事件处理程序时,button
的值表示释放的是哪个按钮。
鼠标滚轮
onmousewheel
事件这可以在任何元素上面触发,最终会冒泡到document
,对应的event
对象除包含鼠标事件的所有标准信息外,还包含一个特殊的wheelDelta
属性。
e.wheelDelta
当用户向前滚动鼠标滚轮时,wheelDelta
是120
的倍数;当用户向后滚动鼠标滚轮时,wheelDelta
是-120
的倍数。通过检测wheelDelta
的正负号就可以确定鼠标滚轮滚动的方向。
Opera 9.5
之前的版本中,wheelDelta
值的正负号是颠倒的(数值也是120
)。Firefox
支持一个名为DOMMouseScroll
的类似事件,信息则保存在detail
属性中,正负号也与标准是颠倒的,当向前滚动鼠标滚轮时,这个属性的值是-3
的倍数,当向后滚动鼠标滚轮时,这个属性的值是3
的倍数。
触摸设备iOS 和Android
ondblclick
事件。双击浏览器窗口会放大画面,而且没有办法改变该行为。mousemove
事件。如果此操作会导致内容变化,将不再有其他事件发生;如果屏幕没有因此变化,那么会依次发生mousedown
、mouseup
和click
事件。轻击不可单击的元素不会触发任何鼠标事件。可单击的元素是指那些单击可产生默认操作的元素(如链接),或者那些已经被指定了onclick
事件处理程序的元素。mousemove
事件也会触发mouseover
和mouseout
事件mousewheel
和scroll
事件。onkeydown
:当用户按下键盘上的任意键时触发,而且如果按住不放的话,会重复触发此事件。onkeypress
:除 Shift
, Fn
, CapsLock
外任意键被按住时(连续触发)。(MDN解释)onkeyup
:当用户释放键盘上的键时触发。键码
e.keyCode
在IE中是e.which
,keyCode
属性的值与ASCII
码中对应小写字母或数字的编码相同。非字符串的常用键码如下:
键 | 键码 | 键 | 键码 |
---|---|---|---|
退格(Backspace ) |
8 | 制表(Tab ) |
9 |
回车(Enter ) |
13 | 上档(Shift ) |
16 |
控制(Ctrl ) |
17 | Alt |
18 |
暂停/中断(Pause/Break ) |
19 | 大写锁定(Caps Lock ) |
20 |
退出(Esc ) |
27 | 上翻页(Page Up ) |
33 |
下翻页(Page Down ) |
34 | 左箭头(Left Arrow ) |
37 |
上箭头(Up Arrow ) |
38 | 右箭头(Right Arrow ) |
39 |
下箭头(Down Arrow ) |
40 | 插入(Ins ) |
45 |
删除(Del ) |
46 | 数字锁(Num Lock ) |
144 |
滚动锁(Scroll Lock ) |
145 |
为了取代keyCode
而新增的e.key
,它的值是一个字符串。在按下某个字符键时,key
的值就是相应的文本字符('a'
,'A'
,'1'
)。在按下非字符键时, key
的值是相应键的名(如“Shift”
或“Down”
)
textInput 事件
“DOM3 级事件”
规范中引入了一个新事件textInput
。根据规范,当用户在可编辑区域中输入字符时,就会触发这个事件。由于textInput
事件主要考虑的是字符,因此它的event
对象中还包含一个data
属性,这个属性的值就是用户输入的字符(而非字符编码)。event
对象上还有一个属性,叫inputMethod
,表示把文本输入到文本框中的方式。
beforeunload
事件当浏览器窗口关闭或者刷新时,会触发beforeunload
事件。当前页面不会直接关闭,可以点击确定按钮关闭或刷新,也可以取消关闭或刷新。
会弹出这个对话框询问用户是否离开,为了显示弹出对话框,必须将event.returnValue
的值设置为要显示给用户的字符串(对IE 及Fiefox 而言),同时作为函数的值返回(对Safari 和Chrome 而言)。
window.addEventListener('beforeunload',function(e){
var e = e || window.event;
var message = "I'm really going to miss you if you go.";
event.returnValue = message;
return message
})
DOMContentLoaded
事件DOMContentLoaded
事件则在形成完整的DOM
树之后就会触发,不理会图像、JavaScript
文件、CSS
文件或其他资源是否已经下载完毕。
readystatechange
事件支持readystatechange
事件的每个对象都有一个readyState
属性,可能包含下列5 个值中的一个。
uninitialized
:对象存在但尚未初始化。loading
:对象正在加载数据。loaded
:对象加载数据完成。interactive
:可以操作对象了,但还没有完全加载。complete
:对象已经加载完毕。如果某个阶段不适用某个对象,则该对象完全可能跳过该阶段;并没有规定哪个阶段适用于哪个对象。显然,这意味着readystatechange
事件经常会少于4 次,而readyState
属性的值也不总是连续的。
对于document
而言,值为"interactive"
的readyState
会在与DOMContentLoaded
大致相同的时刻触发readystatechange
事件。
<script>
(在IE
和Opera
中)和<link>
(仅IE
中)元素也会触发readystatechange
事件,可以用来确定外部的JavaScript
和CSS
文件是否已经加载完成。与在其他浏览器中一样,除非把动态创建的元素添加到页面中, 否则浏览器不会开始下载外部资源。基于元素触发的readystatechange
事件也存在同样的问题, 即readyState
属性无论等于"loaded"
还是"complete"
都可以表示资源已经可用。
pageshow
和pagehide
事件Firefox
和Opera
有一个特性,名叫“往返缓存”
(back-forward cache,或bfcache),可以在用户使用浏览器的“后退”和“前进”按钮时加快页面的转换速度。这个缓存中不仅保存着页面数据,还保存了DOM
和JavaScript
的状态;实际上是将整个页面都保存在了内存里。 如果页面位于bfcache
中,那么再次打开该页面时就不会触发load
事件。尽管由于内存中保存了整个页面的状态,不触发load
事件也不应该会导致什么问题,但为了更形象地说明bfcache
的行为,Firefox
还是提供了一些新事件。
pageshow
:在页面显示时触发,无论该页面是否来自bfcache
。在重新加载的页面中,pageshow
会在load
事件触发后触发;而对于bfcache
中的页面,pageshow
会在页面状态完全恢复的那一刻触发。pageshow
事件的event
对象还包含一个名为persisted
的布尔值属性。如果页面被保存在了bfcache
中,则这个属性的值为true
;否则,这个属性的值为false
。
pagehide
:会在浏览器卸载页面的时候触发,而且是在unload
事件之前触发。与pageshow
事件一样,pagehide
在document
上面触发,但其事件处理程序必须要添加到window
对象。这个事件的event
对象也包含persisted
属性,不过其用途稍有不同。对于pagehide 事件,如果页面在卸载之后会被保存在bfcache
中,那么persisted
的值会被设置为true
。
hashchange
事件在URL
的参数列表(及URL
中“#”
号后面的所有字符串)发生变化时触发。必须要把hashchange
事件处理程序添加给window
对象,然后URL
参数列表只要变化就会调用它。此时的event
对象应该额外包含两个属性:oldURL
和newURL
。
orientationchange
事件移动Safari
中添加了orientationchange
事件,以便开发人员能够确定用户何时将设备由横向查看模式切换为纵向查看模式。
移动Safari
的window.orientation
属性中可能包含3 个值:0 表示肖像模式,90 表示向左旋转的横向模式(“主屏幕”按钮在右侧),-90 表示向右旋转的横向模式(“主屏幕”按钮在左侧)。
只要用户改变了设备的查看模式,就会触发orientationchange
事件。此时的event
对象不包含任何有价值的信息,因为唯一相关的信息可以通过window.orientation
访问到。
移动Safari
提供了一些与触摸(touch
)操作相关的新事件。后来Android
上的浏览器也实现了相同的事件。
touchstart
:当手指触摸屏幕时触发;即使已经有一个手指放在了屏幕上也会触发。touchmove
:当手指在屏幕上滑动时连续地触发。在这个事件发生期间,调用preventDefault()
可以阻止滚动。touchend
:当手指从屏幕上移开时触发。上面这几个事件都会冒泡,也都可以取消。每个触摸事件的event 对象都提供了在鼠标事件中常见的属性外还包含三个用于跟踪触摸的属性。
touches
:表示当前跟踪的触摸操作的Touch
对象的数组。targetTouchs
:特定于事件目标的Touch
对象的数组。changeTouches
:表示自上次触摸以来发生了什么改变的Touch
对象的数组。每个Touch
对象包含下列属性。
clientX
:触摸目标在视口中的x 坐标。clientY
:触摸目标在视口中的y 坐标。identifier
:标识触摸的唯一ID。pageX
:触摸目标在页面中的x 坐标。pageY
:触摸目标在页面中的y 坐标。screenX
:触摸目标在屏幕中的x 坐标。screenY
:触摸目标在屏幕中的y 坐标。target
:触摸的DOM
节点目标。iOS 2.0
中的Safari
还引入了一组手势事件。当两个手指触摸屏幕时就会产生手势,手势通常会改变显示项的大小,或者旋转显示项。
gesturestart
:当一个手指已经按在屏幕上而另一个手指又触摸屏幕时触发。gesturechange
:当触摸屏幕的任何一个手指的位置发生变化时触发。gestureend
:当任何一个手指从屏幕上面移开时触发。只有两个手指都触摸到事件的接收容器时才会触发这些事件。在一个元素上设置事件处理程序,意味着两个手指必须同时位于该元素的范围之内,才能触发手势事件件冒泡,所以将事件处理程序放在文档上也可以处理所有手势事件。此时,事件的目标就是两个手指都位于其范围内的那个元素。
触摸事件和手势事件之间存在某种关系。当一个手指放在屏幕上时,会触发touchstart
事件。如果另一个手指又放在了屏幕上,则会先触发gesturestart
事件,随后触发基于该手指的touchstart
事件。如果一个或两个手指在屏幕上滑动,将会触发gesturechange
事件。但只要有一个手指移开,就会触发gestureend
事件,紧接着又会触发基于该手指的touchend
事件。
每个手势事件的event
对象都包含着标准的鼠标事件属性,也包含两个额外的属性。
rotation
属性表示手指变化引起的旋转角度,负值表示逆时针旋转,正值表示顺时针旋转(该值从0 开始)
scale
属性表示两个手指间距离的变化情况(例如向内收缩会缩短距离);这个值从1 开始,并随距离拉大而增长,随距离缩短而减小。
触摸事件也会返回rotation
和scale
属性,但这两个属性只会在两个手指与屏幕保持接触时才会发生变化。
在JavaScript
中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能。导致这一问题的原因是多方面的。首先,每个函数都是对象,都会占用内存;内存中的对象越多,性能就越差。其次,必须事先指定所有事件处理程序而导致的DOM
访问次数,会延迟整个页面的交互就绪时间。事实上,从如何利用好事件处理程序的角度出发,还是有一些方法能够提升性能的。
使用事件委托,只需在DOM
树中尽量高的层次上添加一个事件处理程序。在通过e.target
属性得到目标元素,然后做出相应的操作。例如,将添加到li
上的点击事件委托到ul
上。
对用户来说最终的结果相同,但这种技术需要占用的内存更少;并且操作新增或者删除低层次的元素,依然不会因为事件未注册而无法执行。
当将事件处理程序指定给元素时,运行中的浏览器代码与支持页面交互的JavaScript
代码之间就会建立一个连接。这种连接越多,页面执行起来就越慢。如前所述,可以采用事件委托技术,限制建立的连接数量。另外,在不需要的时候移除事件处理程序,也是解决这个问题的一种方案
在两种情况下,可能会造成上述问题。第一种情况就是从文档中移除带有事件处理程序的元素时。这可能是通过纯粹的DOM
操作,例如使用removeChild()
和replaceChild()
方法,但更多地是发生在使用innerHTML
替换页面中某一部分的时候。如果带有事件处理程序的元素被innerHTML
删除了,那么原来添加到元素中的事件处理程序极有可能无法被当作垃圾回收。
如果你知道某个元素即将被移除,那么最好手工移除事件处理程序。例如:btn.onclick = null;
、removeEventListener()
、detachEvent()
或者使用事件委托将事件注册在尽量高的层次的元素上。
注意,在事件处理程序中删除按钮也能阻止事件冒泡。目标元素在文档中是事件冒泡的前提。
另一种情况,就是卸载页面的时候,如果在页面被卸载之前没有清理干净事件处理程序,那它们就会滞留在内存中。每次加载完页面再卸载页面时(可能是在两个页面间来回切换,也可以是单击了“刷新”按钮),内存中滞留的对象数目就会增加,因为事件处理程序占用的内存并没有被释放。一般来说,最好的做法是在页面卸载之前,先通过onunload
事件处理程序移除所有事件处理程序。
使用onunload
事件处理程序意味着页面不会被缓存在bfcache
中。如果你在意这个问题,那么可以使用别的方式来移除事件。
事件经常由用户操作或通过其他浏览器功能来触发。但很少有人知道,也可以使用JavaScript
在任意时刻来触发特定的事件,而此时的事件就如同浏览器创建的事件一样。也就是说,这些事件该冒泡还会冒泡,而且照样能够导致浏览器执行已经指定的处理它们的事件处理程序。
createEvent()
和dispatchEvent()
可以在document
对象上使用createEvent()
方法创建event
对象。这个方法接收一个参数,即表示要创建的事件类型的字符串。在DOM2
级中,所有这些字符串都使用英文复数形式,而在DOM3
级中都变成了单数。
UIEvents
:一般化的UI 事件。鼠标事件和键盘事件都继承自UI 事件。MouseEvents
:一般化的鼠标事件。MutationEvents
:一般化的DOM 变动事件。HTMLEvents
:一般化的HTML 事件。没有对应的DOM3 级事件模拟事件的最后一步就是触发事件。这一步需要使用dispatchEvent()
方法,所有支持事件的DOM 节点都支持这个方法。调用dispatchEvent()
方法时,需要传入一个参数,即表示要触发事件的event
对象。
创建鼠标事件对象的方法是为createEvent()
传入字符串"MouseEvents"
。返回的事件对象有一个名为initMouseEvent()
方法,用于指定与该鼠标事件有关的信息。这个方法接收15
个参数。
event.initMouseEvent(type, canBubble, cancelable, view,
detail, screenX, screenY, clientX, clientY,
ctrlKey, altKey, shiftKey, metaKey,
button, relatedTarget);
var btn = document.getElementById("myBtn");
//创建事件对象
var event = document.createEvent("MouseEvents");
//初始化事件对象
event.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0,false, false, false, false, 0, null);
//触发事件
btn.dispatchEvent(event);
event.initKeyEvent (type, bubbles, cancelable, viewArg,
ctrlKeyArg, altKeyArg, shiftKeyArg,
metaKeyArg,keyCodeArg, charCodeArg)
//只适用于Firefox
var textbox = document.getElementById("myTextbox")
//创建事件对象
var event = document.createEvent("KeyEvents");
//初始化事件对象
event.initKeyEvent("keypress", true, true, document.defaultView, false, false,false, false, 65, 65);
//触发事件
textbox.dispatchEvent(event);
event.initCustomEvent (type, bubbles, cancelable, detail)
var div = document.getElementById("myDiv");
var event;
EventUtil.addHandler(div, "myevent", function(event){
alert("DIV: " + event.detail);
});
EventUtil.addHandler(document, "myevent", function(event){
alert("DOCUMENT: " + event.detail);
});
if (typeof document.createEvent == 'function'){
event = document.createEvent("CustomEvent");
event.initCustomEvent("myevent", true, false, "Hello world!");
div.dispatchEvent(event);
}