事件通常与函数配合使用,这样就可以通过发生的事件来驱动函数执行。
事件是文档或者浏览器窗口中发生的,特定的交互瞬间。
事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字。
事件是javaScript和DOM之间交互的桥梁。
你若触发,我便执行——事件发生,调用它的处理函数执行相应的JavaScript代码给出响应。
典型的例子有:页面加载完毕触发load事件;用户单击元素,触发click事件。
事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即DOM事件流。
事件传播的顺序对应浏览器的两种事件流模型:捕获型事件流和冒泡型事件流。
冒泡型事件流:事件的传播是从最特定的事件目标到最不特定的事件目标。即从DOM树的叶子到根。【推荐】
捕获型事件流:事件的传播是从最不特定的事件目标到最特定的事件目标。即从DOM树的根到叶子。
事件捕获的思想就是不太具体的节点应该更早接收到事件,而最具体的节点最后接收到事件。
<html> <head lang="en"> <meta charset="UTF-8"> <title>title> head> <body> <div id="myDiv">Click me!div> body> html>
上面这段html代码中,单击了页面中的
在冒泡型事件流中click事件传播顺序为 在捕获型事件流中click事件传播顺序为document—》—》—》 note: 1)、所有现代浏览器都支持事件冒泡,但在具体实现中略有差别: IE5.5及更早版本中事件冒泡会跳过元素(从body直接跳到document)。 IE9、Firefox、Chrome、和Safari则将事件一直冒泡到window对象。 2)、IE9、Firefox、Chrome、Opera、和Safari都支持事件捕获。尽管DOM标准要求事件应该从document对象开始传播,但这些浏览器都是从window对象开始捕获事件的。 3)、由于老版本浏览器不支持,很少有人使用事件捕获。建议使用事件冒泡。 DOM标准采用捕获+冒泡。两种事件流都会触发DOM的所有对象,从document对象开始,也在document对象结束。
DOM标准规定事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。 note: 1)、尽管“DOM2级事件”标准规范明确规定事件捕获阶段不会涉及事件目标,但是在IE9、Safari、Chrome、Firefox和Opera9.5及更高版本都会在捕获阶段触发事件对象上的事件。结果,就是有两次机会在目标对象上面操作事件。 2)、并非所有的事件都会经过冒泡阶段 。所有的事件都要经过捕获阶段和处于目标阶段,但是有些事件会跳过冒泡阶段:如,获得输入焦点的focus事件和失去输入焦点的blur事件。 更多详情见:http://www.cnblogs.com/starof/p/4066381.html 常用的事件主要有: 简单来讲,HTML 事件处理程序是直接在HTML中绑定事件,如下 扩展函数作用域,来看下面的代码: 如果当前元素是一个表单输入元素,浏览器内部大概是这样实现的: 这里只总结一些常见的事件类型 效果图 鼠标由左侧从上到下依次经过所有 div 的情况,输出 DOM2 级的变动(mutation)事件能在 DOM 中的某一部分发生变化时给出提示,比如 DOM 节点的插入、移除、特性被修改等等 第一步:document.createEventObject() 转载于:https://www.cnblogs.com/klb561/p/10161148.html
JavaScript中常用的事件
1.onclick事件
点击事件(onclick并不是js中的方法,onclick只是浏览器提供js的一个dom接口,让js可以操作dom,所以onclick大小写都是没问题的,比如HTML代码就不用区分大小写)
例:
<%@pagelanguage="Java"import="java.util.*"pageEncoding="UTF-8"%> "-//W3C//DTD HTML 4.01 Transitional//EN">
得到焦点:
测试onscroll方法
测试onscroll方法
测试onscroll方法
6.onsubmit事件 属于 2.鼠标相关事件 1.onmousemove和onmouseout和onmouseover事件 Onmouseover:鼠标移动到某对象范围的上方时,触发事件调用函数。注意:在同一个区域中,无论怎样移动都只触发一次函数。 Onmouseout:鼠标离开某对象范围时,触发事件调用函数。 Onmousemove:鼠标移动到某对象范围的上方时,触发事件调用函数。注意:在同一个区域中,只要鼠标动一次就触发一次事件。 例: <%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%>
(1)单击事件:onclick。用户单击鼠标按键时产生的事件,同时。nclick指定的事件处理程序或代码将被调用执行.
(2)改变事件:onchange。当text或textarea元素内的字符值改变或select表格选项状态改变时发生该事件。
(3)选中事件:onselect。当text或textarea对象中的文字被选中时会引发该事件。如:
(5)失去焦点事件:onblur.失去焦点事件正好与获得焦点事件相对,当text或textarea以及select对象不再拥有焦点而退出后台时,引发该事件。
(6)载人文件事件:onload,’当页面文件载人时产生该事件。onload的一个作用就是在首次载人一个页面文件时检测cookie的值,并用一个变量为其赋值,使它可以被源代码使用,本事件是window的事件,但是在HTML中指定事件处理程序时,一般把它写在标记中。如:
(7)卸载文件事件:onunload。与载人文件事件。nload正好相反,当Web页面退出时引发的事件,并可更新。ookie的状态。如:
(8)鼠标镇盖事件:onmouseover, onmouseover是当鼠标位于元素上方时所引发的事件。如:
(9)鼠标离开事件:onmouseout, onmouseout是当鼠标离开元素时引发的事件。如果和鼠标覆盖事件同时使用,可以创建动态按钮的效果。
(10)一般事件。
ondbclick:鼠标双击事件。
onkeypress:当键盘上的某个键被按下并且释放时触发的事件,要求页面内必须有激活的对象。
onkeydown:当键盘上某个键被按下时触发的事件,要求页面内必须有激活的对象。
onkeyup:当键盘上某个键被放开时触发的事件,要求页面内必须有激活的对象。
(11)页面相关事件。
onabort:图片在下载时被用户中断时触发的事件。
onbeforeunload:当前页面的内容将要被改变时触发的事件。DOM事件流
事件处理程序
HTML 事件处理程序
<input type="button" value="Click Me" onclick="alert("Clicked")" />
注意事项:
&
、“”
、<
、>
,因为这是在HTML中绑定的,会造成浏览器解析DOM结构错误。
<form method="post"> <input type="text" name="username" value="lzh"> <input type="button" value="Click Me" onclick="alert(value);alert(username.value);"> form>
function () { with (document) { with (this.form) { with (this) { //元素属性值 } } } }
form
元素,调用username
会报错,所以不论是服务端渲染还是Ajax请求回来数据再渲染,最好还是把form结构写完整。
扩展作用域有三个缺点:
try{}catch(ex){}
,分离的写法可以在DOMContentLoaded之后再绑定。DOM0级事件处理程序
window
和document
)都有自己的事件处理程序属性,这些属性通常全部小写。使用 DOM0 级指定的事件处理程序被认为是元素的方法。this
引用当前元素。通过 this
可以访问元素的任何属性和方法。DOM0 级事件处理程序在冒泡阶段被处理。var btn = document.getElementById("myBtn"); btn.onclick = function () { alert(this.id); //"myBtn" };
DOM2级事件处理程序
addEventListener()
包含三个参数,要处理的事件名、事件处理函数、布尔值,布尔值为true,表示在捕获阶段调用事件处理程序,反之在冒泡阶段调用。this
也指向 addEventListener
的那个元素。removeEventListener
无法移除匿名函数的事件处理程序。var btn = document.getElementById("myBtn"); var handler = function () { alert(this.id); }; btn.addEventListener("click", handler, false); //这里省略了其他代码 btn.removeEventListener("click", handler, false); // 有效!
IE事件处理程序
attachEvent
detachEvent
接收两个参数,事件处理程序名称、事件处理程序函数。由于IE8及更早版本只支持事件冒泡,所以该事件处理程序只支持事件冒泡。this
指向 'window'。跨浏览器的事件处理程序
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; } } };
this
指向 window
。on + name
的形式呢? 之前一直怀疑 (1).xhr.onreadystatechange()
和 (2).DOMNodeInserted
事件,这里我多虑了,经过验证,(1).是支持 DOM2 级事件的,(2).天生就是 DOM2 级的。这里只是为了打消我的疑虑,记录下来。事件对象
DOM 中的事件对象
event
对象传入事件处理程序, IE9 及更高版本可以。无论指定事件处理程序时使用什么方法(DOM0 级 DOM2 级),HTML 事件处理程序可以通过访问 event
变量得到 event
对象。
target
事件的目标currentTarget
绑定事件的元素,与 'this' 的指向相同stopPropagation()
取消事件的进一步捕获或冒泡。如果bubbles为true,则可以使用这个方法stopImmediatePropagation()
取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用(DOM3级事件中新增)preventDefault()
取消事件的默认行为,比如点击链接跳转。如果 cancelable
是 true
,则可以使用这个方法type
被触发的事件类型eventPhase
调用事件处理程序的阶段:1表示捕获阶段,2表示“处于目标”,3表示冒泡阶段
this
target
currentTarget
举例:document.body.onclick = function(event){ alert(event.currentTarget === document.body); //true alert(this === document.body); //true alert(event.target === document.getElementById("myBtn")); //true };
event.type
与 switch case
组合,可以通过一个函数处理多个事件。event
对象才会存在;一旦事件处理程序执行完成,event
对象就会被销毁。IE 中的事件对象
event
作为 window
的一个属性存在。(从 IE9 开始,event 可以从参数中获得)attachEvent
添加的事件处理程序,event
作为参数传入,也可以通过 window
来访问 event
对象。event
变量得到 event
对象。
cancelBubble
设置 true
or false
可以取消事件冒泡returnValue
设置 true
or false
可以取消事件的默认行为。srcElement
事件的目标(与DOM中的 target
相同)
attachEvent
中的 event.srcElement === this
吗? 答案是否定的,因为前面说到过 attachEvent
中 this
指向 window
, DOM0 级、DOM2 级 事件处理程序 this
才指向 event.target / window.event.srcElement
跨浏览器的事件对象
var EventUtil = { getEvent: function(event){ return event ? event : window.event; // window.event DOM0级时IE }, getTarget: function(event){ return event.target || event.srcElement; // event.srcElement for IE }, preventDefault: function(event){ if (event.preventDefault){ event.preventDefault(); } else { event.returnValue = false; // IE } }, stopPropagation: function(event){ if (event.stopPropagation){ event.stopPropagation(); } else { event.cancelBubble = true; // IE } } };
事件类型
UI事件类型
window
上面的 load 事件。EventUtil.addHandler(window, "load", function(){ var image = document.createElement("img"); EventUtil.addHandler(image, "load", function(event){ event = EventUtil.getEvent(event); alert(EventUtil.getTarget(event).src); }); document.body.appendChild(image); image.src = "smile.gif"; //在此之前要先指定事件处理程序 });
window
上触发,IE、Safari、Chrome 和 Opera 会在浏览器窗口变化了 1 像素时就触发 resize 事件,然后随着变化不断重复触发。Firefox 则只会在用户停止调整窗口大小时才会触发。
document.body.scrollTop + document.documentElement.scrollTop
的方式获取 scrollTop 的值,因为两者之一会等于0,或者使用 document.body.scrollTop || document.documentElement.scrollTop
,两者效果一致。焦点事件
鼠标与滚轮事件
click
在用户单击住鼠标按钮或按下回车键时触发。 触发顺序 mousedown mouseup click,如果 mousedown、mouseup 其中之一被取消,就不会触发 click 事件。dblclick
触发顺序 mousedown mouseup click mousedown mouseup click dblclick, 如果中间有事件被取消,dblclick 也不会被触发mousedown
用户按下了任意鼠标按钮时触发。mouseup
用户释放按钮时触发mouseenter
在鼠标光标从元素外部首次移动到元素范围之内时触发。不冒泡,而且在光标移动到后代元素上不会触发。DOM2 级事件并没有定义这个事,但 DOM3 级事件将它纳入了规范。IE、Firefox9+和Opera支持这个事件。mouseleave
在位于元素上方的鼠标光标移动到元素范围之外时触发。不冒泡,而且在光标移动到后代元素上不会触发。DOM2 级事件并没有定义这个事,但 DOM3 级事件将它纳入了规范。IE、Firefox9+ 和 Opera 支持这个事件。mouseover
在鼠标指针位于一个元素外部,然后用户将其首次移入另一个元素边界之内时触发。不能通过键盘触发这个事件。mouseout
在鼠标指针位于一个元素上方,然后用户将其移入另一个元素时触发。又移入的另一个元素可能位于前一个元素的外部,也可能是这个元素的子元素。不能通过键盘触发这个事件。
html> <html lang="zh-cn"> <head> <title>test1title> <meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="test1.css"> head> <body> <div class="mouseover"> <div class="sub-mouseover"> div> div> <div class="mouseenter"> <div class="sub-mouseenter"> div> div> <script src="test1.js">script> body> html>
.wrap {
width: 200px; height: 100px; } .mouseover { background: pink; } .mouseenter { margin-top: 30px; background: gray; } .sub-mouseover, .sub-mouseenter { width: 100px; height: 50px; background: #AE81FF; }
var div1 = document.querySelector(".mouseover"), div2 = document.querySelector(".mouseenter"); div1.addEventListener("mouseover", function(){ console.log("div1 mouseover"); }); div1.addEventListener("mouseout", function(){ console.log("div1 mouseout"); }) div2.addEventListener("mouseenter", function(){ console.log("div2 mouseenter"); }) div2.addEventListener("mouseleave", function(){ console.log("div2 mouseleave"); })
div1 mouseover
div1 mouseout
div1 mouseover
div1 mouseout
div2 mouseenter
div2 mouseleave
mousemove
当鼠标指针在元素内部移动时重复地触发。不能通过键盘触发这个事件。dblclick
IE8 及之前版本中的实现有一个小bug,因此在双击事件中,会跳过第二个mousedown 和click事件,其顺序如下:mousedown
mouseup
click
mouseup
dblclick
,但还是会触发 dblclick
事件event
都有 clientX
clientY
属性,表示在视口中客户区的坐标位置,这些值不包括页面滚动的距离,因此这个位置并不表示鼠标在页面上的位置:
var div = document.getElementById("myDiv"); EventUtil.addHandler(div, "click", function(event){ event = EventUtil.getEvent(event); var pageX = event.pageX, pageY = event.pageY; if (pageX === undefined){ pageX = event.clientX + (document.body.scrollLeft || document.documentElement.scrollLeft); } if (pageY === undefined){ pageY = event.clientY + (document.body.scrollTop || document.documentElement.scrollTop); } alert("Page coordinates: " + pageX + "," + pageY); });
event
中获得修改键。var div = document.getElementById("myDiv"); EventUtil.addHandler(div, "click", function(event){ event = EventUtil.getEvent(event); 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(",")); });
mouseover
mouseout
时的 event.relatedTarget,不做详细记录。mousedown
mouseup
是在按下/释放任意鼠标按钮时触发的,所以通过 event.button: 0(左) 1(中) 2(右) 可以判断按的是哪个键,但是IE8 及更低版本的浏览器不支持,有兼容写法,此处不详细叙述。EventUtil.getButton
有详细实现。event.whellDelta
为正数时,向前滚动(回到顶部、页面向下滑动),负数则反过来,这个值是120的倍数,Opera低版本中正负相反,火狐中有自己的一套方法,这里不做详细记录。click
之外的鼠标事件。因为这个不能通过键盘触发,不利于屏幕阅读器访问。此处不详细记录。键盘与文本事件
keydown
: 当用户按下键盘上的任意键时触发,而且如果按住不放的话,会重复触发此事件。keypress
当用户按下键盘上的字符键时触发,而且如果按住不放的话,会重复触发此事件。按下Esc 键也会触发这个事件。Safari 3.1 之前的版本也会在用户按下非字符键时触发keypress事件。keyup
:当用户释放键盘上的键时触发。keydown
、keypress
、keyup
,keydown
、keypress
都是在文本框发生变化之前被触发的; keyup
事件则是在文本框已经发生变化之后被触发的。String.fromCharCode()
可以转换成实际的字符key
和 char
,其中 key
可以直接得到 "k"、"K"、"Shift" 等, char
属性在按下字符键时行为与 key
相同,在按下非字符键时为 null
,但是支持还不完整,chrome 总是输出 undefined。keyIdentifier
Chrome 已经不推荐使用textInput
: 在文本插入文本框之前会触发textInput 事件。目的是代替keypress,退格键不会触发textInput,但是会触发keypress(只要改变文本),只有真正可以编辑的区域才会触发textInput,但是keypress获得焦点即可触发。event.data中包含用户的输入,拼音输入法中输入过程的拼音不会触发该事件。变动事件
HTML5 事件
EventUtil.addHandler(window, "load", function(event){ var div = document.getElementById("myDiv"); EventUtil.addHandler(div, "contextmenu", function(event){ event = EventUtil.getEvent(event); EventUtil.preventDefault(event); var menu = document.getElementById("myMenu"); menu.style.left = event.clientX + "px"; menu.style.top = event.clientY + "px"; menu.style.visibility = "visible"; }); EventUtil.addHandler(document, "click", function(event){ document.getElementById("myMenu").style.visibility = "hidden"; }); });
EventUtil.addHandler(window, "beforeunload", function(event){ event = EventUtil.getEvent(event); var message = "I'm really going to miss you if you go."; event.returnValue = message; return message; });
EventUtil.addHandler(window, "DOMContentLoaded", function(event){ alert("Content loaded."); }); EventUtil.addHandler(window, "load", function(event){ alert("Window loaded."); });
event.persisted
属性,为 true
代表页面来自bfcache,同样 pagehide 事件触发时,如果页面被保存到 bfcache 中,则该属性为 true。支持pageshow、pagehide 事件的浏览器有 Firefox、Safari5+、Chrome 和 Opera。 IE9 及以前的版本不支持这两个事件。指定了 onunload 事件处理程序的页面会被自动排除在 bfcache 之外。EventUtil.addHandler(window, "hashchange", function(event){ console.log(location.hash); })
设备事件
触摸与手势事件
function handleTouchEvent(event) { //only for one touch if (event.touches.length == 1) { var output = document.getElementById("output"); switch (event.type) { case "touchstart": output.innerHTML = "Touch started (" + event.touches[0].clientX + "," + event.touches[0].clientY + ")"; break; case "touchend": output.innerHTML += "
Touch ended (" + event.changedTouches[0].clientX + "," + event.changedTouches[0].clientY + ")"; break; case "touchmove": event.preventDefault(); //prevent scrolling output.innerHTML += "
Touch moved (" + event.changedTouches[0].clientX + "," + event.changedTouches[0].clientY + ")"; break; } } }
内存和性能
事件委托
<body>
<ul id="myLinks"> <li id="goSomewhere">Go somewhereli> <li id="doSomething">Do somethingli> <li id="sayHi">Say hili> ul> <script type="text/javascript"> (function(){ var list = document.getElementById("myLinks"); EventUtil.addHandler(list, "click", function(event){ event = EventUtil.getEvent(event); var target = EventUtil.getTarget(event); switch(target.id){ case "doSomething": document.title = "I changed the document's title"; break; case "goSomewhere": location.href = "http://www.wrox.com"; break; case "sayHi": alert("hi"); break; } }); })();
click
、mousedown
、mouseup
、keydown
、keyup
和 keypress
移除事件处理程序
模拟事件
DOM 中的事件模拟
模拟鼠标事件
<body>
<input type="button" value="Click me" id="myBtn" /> <input type="button" value="Send click to the other button" id="myBtn2" /> <p>This example works in DOM-compliant browsers (not IE).p> <script type="text/javascript"> (function(){ var btn = document.getElementById("myBtn"); var btn2 = document.getElementById("myBtn2"); EventUtil.addHandler(btn, "click", function(event){ alert("Clicked!"); alert(event.screenX); //100 }); EventUtil.addHandler(btn2, "click", function(event){ //create event object var event = document.createEvent("MouseEvents"); //initialize the event object event.initMouseEvent("click", true, true, document.defaultView, 0, 100, 0, 0, 0, false, false, false, false, 0, btn2); //fire the event btn.dispatchEvent(event); }); })();
模拟键盘事件
createEvent()
并传入 "KeyboardEvent" ,返回键盘事件,有 initKeyEvent()
方法。这个方法接收一下参数
DOM3 级不提倡 keypress
事件, 因此只能模拟 keydown
keyup
IE 中的事件模拟
第二步: 通过赋值的方式初始化事件对象,就是 event.screenX = 0
这些
第三步:btn.fireEvent("onclick", event);