在触发DOM上的某个事件时,会产生一个事件对象event,这个事件对象包含着所有与事件有关的信息,例如事件是冒泡还是捕获,事件的目标,鼠标坐标,键盘按下的键,等等信息,不要太好用
下面一起来看看event事件对象都有哪些内容吧。
小提示:在页面中按 Ctrl + F 可以查询关键字,以便搜索到你想要的内容。
兼容DOM的浏览器会将一个event对象传入到事件处理程序中。无论DOM0级或者DOM2级方法,都会传入event对象,例如:
<body>
<ul>
<li data-index="0">Ⅰ</li>
<li data-index="1">Ⅱ</li>
<li data-index="2">Ⅲ</li>
<li data-index="3">Ⅳ</li>
<li data-index="4">Ⅴ</li>
</ul>
<script>
var oUl = document.querySelector("ul");
var aLi = document.querySelectorAll("ul>li");
oUl.addEventListener("click",function(event){
alert(event.target.getAttribute("data-index"))//弹出我自定义的索引值
})
aLi[0].onclick = function(e){
alert(e.target.getAttribute("data-index"))//弹出我自定义的索引值
}
</script>
</body>
据上述代码,有两点需要提及一下
- 浏览器确实会将event对象传入到事件处理程序中,但对于形参设置成什么,并没有要求,只要
保持形参和实参相统一
就好了,一般会使用event或 e。要是不统一,一定要在函数体内部使用event。- 这里我使用了事件委托,target表示事件的目标(也就是谁触发了事件,是第一个li还是第二个li?),下面会解释。
接下来看看效果:
可以看到,两个事件都被触发了,分别弹出了第一个li的索引值。
在这个示例中,event事件对象起到的作用就是利用了里面的target属性,来帮我找到了是谁触发了Ul的点击事件,然后弹出它的索引值。
通过这个示例,引出所有事件都会有的event对象的属性和方法(后面我会解析包括鼠标,键盘在内的所有event的属性和方法):
属性/方法 | 类型 | 读/写 | 说明 |
---|---|---|---|
bubbles | Boolean | 只读 | 表明事件是否冒泡 |
cancelable | Boolean | 只读 | 表明是否可以取消时间的默认行为 |
currentTarget | Element | 只读 | 谁绑定的事件,currentTarget 就是谁,与this类似 |
defaultprevented | Boolean | 只读 | 值为true则表示已经调用了preventDefault( ) |
eventPhase | Integer | 只读 | 调用事件处理程序的阶段:1表示捕获阶段,2表示目标阶段,3表示冒泡阶段 |
preventDefault( ) | Function | 只读 | 取消事件的默认行为。如果cancelable为true,则可以使用这个方法 |
stopImmediatePropagation( ) | Function | 只读 | 取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用 |
stopPropagation( ) | Function | 只读 | 取消事件的进一步捕获或冒泡 |
target | Element | 只读 | 事件的目标,谁触发了事件就是谁 |
isTrusted | Boolean | 只读 | 为true表示事件是浏览器生成的,false则表示事件是开发人员通过JavaScript创建的 |
type | String | 只读 | 被触发的事件的类型,例如click,mouseout,blur |
view | AbstractView | 只读 | 与事件关联的抽象视图。等同于发生事件的window对象 |
光是所有事件都有的属性方法已经如此之多,头顶发凉~~
下面着重分析一下较重要的点:
<script>
var oUl = document.querySelector("ul");
var aLi = document.querySelectorAll("ul>li");
oUl.addEventListener("click",function(e){
console.log("this === "+this.tagName)
console.log("e.currentTarget === "+e.currentTarget.tagName)
console.log("e.target === "+e.target.tagName)
console.log("e.target的索引值 === "+e.target.getAttribute("data-index"))
console.log("=================================")
})
</script>
代码说明: tagName只是为了获取标签名,getAttribute只是为了获取li的索引值,可以更直观的看出区别
可以明显的看到,this和currentTarget始终相同,等于ul。而target始终为li。
currentTarget :谁绑定了事件,我就指向谁
target : 谁触发了事件,我就指向谁
type能够返回事件的类型
,因此,我们只需要定义一个函数,让不同的事件绑定一个相同的函数
看看实例:
<script>
var oInput = document.querySelector("input")
function show(e) {
switch (e.type) {
case "click":
alert("你点击了我");
break;
case "mouseover":
alert("你移入了我");
break;
case "mouseout":
alert("你移出了我");
break;
}
}
oInput.addEventListener("click",show)
oInput.addEventListener("mouseover",show)
oInput.addEventListener("mouseout",show)
</script>
例如,链接的默认行为就是在单击时会跳转到指定的URL,如果想阻止这一默认行为,请使用 preventDefault( )
<script>
var oA = document.querySelector("a");
oA.addEventListener("click",function(e){
e.preventDefault();
})
</script>
这个可能会有点绕,我们来细分一下,首先看看代码
<script>
var oSection = document.querySelector("section");
var oDiv = document.querySelector("div");
oDiv.addEventListener("click",function(e){
alert("我是子盒子,我在捕获阶段")
},true)
oDiv.addEventListener("click",function(e){
alert("我是子盒子,我在冒泡阶段")
})
oSection.addEventListener("click",function(e){
alert("我是父盒子,我在捕获阶段")
},true)
oSection.addEventListener("click", function (e) {
alert("我是父盒子,我在冒泡阶段")
})
oBody.addEventListener("click",function(e){
alert("我是body,我在捕获阶段")
},true)
oBody.addEventListener("click", function (e) {
alert("我是body,我在冒泡阶段")
})
</script>
代码说明:div-section-body为嵌套关系,div最小,若点击div,则事件传播流程如下图
可以看到,从body捕获到body冒泡,用箭头链接起来了,把箭头想象成一条线,将它们串起来。在何处使用e.stopPropagation(),就相当于在何处剪断这根线(事件是从线的最左端端开始的)
Ul事件指的是那些不一定与用户操作有关的事件。
事件名:load
示例,当图片加载完毕时
<body>
<img src="./Img/time-1.png">
<script>
var oImage = document.querySelector("img");
oImage.addEventListener("load",function(){
alert("加载完毕")
})
</script>
</body>
事件名:unload
用户从一个页面跳转到另一个页面时,就会发生unload事件。而利用这个事件最多的情况就是清除引用,避免内存泄漏。
具体参照load事件
事件名:select
事件名:resize
事件名:scroll
在混杂模式下,可以通过body元素的 scrollLeft 和 scrollTop 来监控这一变化
而在标准模式下,除Safari之外的所有浏览器都会通过html元素来监控这一变化。
事件名:blur
事件名:focus
事件名:focusout
事件名:focusin
事件名:click
在用户单击主鼠标按钮(一般是左边的按钮)或者按下键盘的回车键时触发。这一点对确保易访问性很重要,意味着onclick事件处理程序可以通过鼠标也可以通过键盘执行
事件名:dblclick
在用户双击主鼠标时触发
事件名:mousedown
事件名:mouseup
在用户释放鼠标按钮时触发,不能通过键盘触发这个事件
click 和 dblclick 事件都会依赖于其他的先行事件;而mousdown 和 mouseup 不受影响,因为一个click事件也触发了mousdown 和 mouseup
不能通过键盘触发这个事件
事件名:mouseenter
这个事件不但不冒泡,而且在光标移动到后代元素上不会触发
事件名:mouseleave
这个事件不但不冒泡,而且在光标移动到后代元素上不会触发
事件名:mousemove
重复触发
事件名:mouseover
在光标位于一个元素上,然后又移入另一个元素时触发(这个元素可以是子元素),不能通过键盘触发这个事件
事件名:mouseout
同上!
IE6首先实现了mousewheel事件。此后,Opera,Chrome 和 Safari也都实现了这个事件。但Firefox不同,它的类似事件是DOMMouseScroll,而且它有关鼠标滚轮的信息则保存在detail属性中(下面会提到)
事件名:mousewheel
事件名:DOMMouseScroll(火狐)
无论向上向下滚动,都会触发,最终会冒泡到 document 或 window对象
小提示:如果你想让指定元素触发滚动事件,而不想让文档滚动,可以取消默认事件
clientX,clientY
首先我设置了body的宽高均为3000px
screenX,screenY
这个很好懂,就不演示了
虽然鼠标事件主要是使用鼠标来触发的,但在按下鼠标时键盘上的某些键的状态也可以影响到所要采取的操作。这些修改键就是Shift、Ctrl、Alt和Meta(在Windows键盘中是Windows键,在苹果机中是Cmd键) ,它们通常被用来修改鼠标事件的行为。
DOM为此规定了4个属性,表示这些修改键的状态:shiftKey,ctrlKey,altKey和metaKey。这些属性中包含的都是布尔值,如果相应的键被按下了,则值为true,否则值为false。当某个鼠标事件发生时,通过检测这几个属性就可以确定用户是否同时按下了其中的键。
摘自《JavaScript高级程序设计》
示例:
<body>
<P></P>
<form action=" ">
<input type="button" value="clickMe">
</form>
<script>
var oP = document.querySelector("p");
var oInput = document.querySelector("input");
oInput.addEventListener("click", function (e) {
var keys = new Array();
if (event.shiftKey) {
keys.push("shift");;
}
if (event.ctrlKey) {
keys.push("ctrl");
}
if (event.altKey) {
keys.push("alt");
}
if (event.metaKey) {
keys.push("meta");
}
alert("Keys: " + keys.join(","));
})
window.addEventListener("keydown",function(e){//键盘事件会讲到
oP.innerText = e.key
})
</script>
</body>
对于mousedown 和 mouseup 在其event对象中存在一个
button
属性,有如下三个值:
0 表示鼠标左键
1 表示鼠标中间
2 表示鼠标右键
通过event.button可以知道哪个鼠标按钮被按下
detail
单击或者相继的发生一次mousedown 和 mouseup 事件算作一次单击。detail属性从1开始计数,每次单击后都会递增,如果鼠标在mousedown和mouseup之间移动了位置,则detail会被重置。
亲测连续且不移动的点击会递增,当间隔了一定时间后再次点击(此时没有移动),也会清零。另外,在火狐上只能 1、2、3循环,不会递增。
wheelDelta
detail (火狐)
当用户滚动滚轮时,wheeldelta是120的倍数。若向前滚动是120,向后则是 ﹣120(数值根据浏览器,在火狐中是4的倍数)
ios和android设备的实现非常特别,因为这些设备没有鼠标。在面向iphone和ipad中的开发时,要记住以下几点:
- 不支持dblclick事件,双击浏览器窗口会放大画面,而且没有办法改变该行为
- 轻击可单击元素触发mousemove事件。如果此操作会导致内容变化,将不再有其他事件发生;如果屏幕没有因此变化,那么会依次发生mousedown、mouseup和click事件。轻击不可单击的元素不会触发任何事件,可单击的元素时指那些单击产生默认操作的元素,或者那些已经被指定了onclick事件处理程序的元素
- mousemove事件也会触发mouseover和mouseout事件
摘自《JavaScript高级程序设计》
键盘事件与鼠标事件一样,都支持相同的修改键。
keydown
按住不放会重复触发
keypress
按住不放会重复触发
keyup
keyCode
keyCode属性的值与ASCII码中会包含一个代码,与键盘上一个特定的键对应。
charCode
这个属性只有在发生keypress事件时才包含值,而且这个值是按下的那个键所代字符的ASCII编码
这个属性在DOM3级事件中发生了变化,详情看下条,如果仍使用了charCode,只会返回 0
key
DOM3级事件中不再包含charCode属性,而是包含了两个新属性:key 和 char
key返回的值是一个字符串。在按下某个字符键时,它的值就是相对应的文本。在按下非字符键时,它的值是相对应键的名,如 “Shift” ,“Alt”。
变动事件能在DOM某一部分发生变化时给出提示
事件名:DOMNodeRemoved
在使用removeChild( ) 或 replaceChild( ) 从DOM中删除节点时,首先会触发DOMNodeRemoved事件,这个事件的目标(event.target)是被删除的节点,而event.relatedNode属性中包含着对目标父节点的引用。这个事件会冒泡,所以可以在DOM的任何层次上面处理它。
示例:
<body>
<ul>
<li data-index="0"><p>Ⅰ</p></li>
<li data-index="1">Ⅱ</li>
<li data-index="2">Ⅲ</li>
<li data-index="3">Ⅳ</li>
<li data-index="4">Ⅴ</li>
</ul>
<form action=" ">
<input type="button" value="clickMe">
</form>
<script>
var oInput = document.querySelector("input");
var oUl = document.querySelector("ul");
oInput.addEventListener("click",function(){
oUl.removeChild(oUl.children[0])
})
window.addEventListener("DOMNodeRemoved",function(e){
alert("我删除的li的索引值是:"+e.target.getAttribute("data-index"))
alert("它的父元是:"+e.relatedNode.tagName)
})
</script>
</body>
注意看下面的引文:
如果被移出的节点包含子节点,那么在其所有的子节点以及这个被移出的节点上会相继触发DOMNodeRemovedFromDocument事件。但因为这个事件不冒泡,所以只有直接指定给其中一个子节点的事件处理程序才会被调用。这个事件的目标是相应的子节点或者那个被移出的子节点,除此之外event对象不包含任何信息
事件名:DOMNodeRemovedFromDocument
示例:
html部分与上述代码相同
<script>
var oInput = document.querySelector("input");
var oUl = document.querySelector("ul");
oInput.addEventListener("click",function(){
oUl.removeChild(oUl.children[0])
})
window.addEventListener("DOMNodeRemoved",function(e){
alert("被删除的li的索引值是:"+e.target.getAttribute("data-index"))
alert("它的父元是:"+e.relatedNode.tagName)
})
//给被删除的LI绑定时,会触发
oUl.children[0].addEventListener("DOMNodeRemovedFromDocument",function(e){
alert("我是"+e.target.tagName+"元素,我被删除了,因为我里面有子元素,所以这个事件触发了")
})
//给被删除的LI的子元素P绑定时,也会触发
oUl.children[0].children[0].addEventListener("DOMNodeRemovedFromDocument",function(e){
alert("我是"+e.target.tagName+"元素,很不幸,因为我的父元素被删除了,所以这个事件触发了")
})
</script>
事件名:DOMSubtreeModified
删除节点时,随着上面两个事件的触发,紧随其后的是DOMSubtreeModified事件。这个事件的目标是被移出节点的父节点;此时的event对象也不会提供与事件相关的任何信息。
抱歉,由于与插入节点相关的事件,跟删除节点是一个模子里刻出来的(与删除事件一一对应),这里不费力气阐述了,改日再战^^
罗列一下事件:
事件名:DOMNodeInserted
事件名:DOMNodeInsertedIntoDocument
事件名:DOMSubtreeModified
DOM规范没有涵盖所有浏览器支持的所有事件。很多浏览器出于不同的目的——满足用户需求或解决特殊问题,还实现了一些自定义的事件。
事件名:contextmenu
开发人员面临的主要问题是如何确定应该显示上下文菜单,以及如何屏蔽与该操作关联的默认上下文菜单。为了解决这个问题,就出现了contextmenu事件,用以表示何时应该显示上下文菜单,以便开发人员取消默认的上下文菜单而提供自定义菜单。
示例:
<script>
var oUl = document.querySelector("ul")//可以自己设定ul、li的样式
window.addEventListener("contextmenu", function (e) {
e.preventDefault();
oUl.style.display = "block";
oUl.style.left = e.clientX + "px";
oUl.style.top = e.clientY + "px";
})
window.addEventListener("click",function(){
oUl.style.display = "none";
})
</script>
事件名:beforeunload
在用户离开页面时询问是否真想离开
至此,大多数事件、事件对象都写到了,还有些许没有提及的,或者遗忘、漏掉的,后续会补充。
结语:若文章有错误的地方,烦请在评论区指出。当然,我会不定时的重新编辑写过的文章,查错及优化,希望能将最好的文章展现给读者。如果觉得文章写的不错,请奖励我一个赞^ ^
我的与此文章相关的文章:
DOM事件处理函数、DOM0,DOM2的优缺点
DOM事件流,冒泡 | 捕获 | 委托 ,详解