事件流
<body> <button>点击</button> </body>
1.事件冒泡(一般用)
以上面代码为例,当点击button时,click事件会从button开始,一直往上级传播(button-body-html-document)
jQuery的事件委托用的是事件冒泡原理
2.事件捕获(特殊用)
与事件冒泡相反(document-html-body-button)
事件的三个阶段(event.eventPhase)
1.事件捕获阶段
2.事件目标阶段
3.事件冒泡阶段
DOM 0级事件处理
ele.onclick = function() { // 代码 };
onclick 点击 onmousemove 鼠标移动到该元素上时 onmouseover 鼠标移出该元素 onfocus 获取焦点时
onblur失去焦点时
缺点:一次只能绑定一个事件。而且同个元素绑定多个时,会覆盖上面的
取消绑定:例如ele.onclick = null;
DOM 2级事件处理
addEventListener(“事件名(没有on)”, 事件处理函数, boolean);(boolean为true时,捕获事件;false时,冒泡事件)
attachEvent(“事件名(带on)”, 事件函数); (IE8及以下支持)
取消绑定:removeEventListener(“事件名”,相同的事件函数);
detachEvent(“事件名”,相同的事件函数);
注意:attachEvent中的事件函数的this是window,而addEventListener是当前绑定对象
绑定事件与取消绑定中的事件函数不要用匿名函数(因为new一次就是不同的对象),所以要在外面定义好,直 接使用函数名。
addEventListener与attachEvent的区别:
1.参数个数不同
2.事件类型有无on
3.addEventListener IE9,其他浏览器都支持
attachEvent IE,Opera支持
4.this不同,addEventListener是当前绑定对象,而attachEvent是window
兼容性后面的文章再写
事件对象(全部属性都是只读)
event.currentTarget 处理事件的那个函数(就是绑定事件那个函数)
this始终===event.currentTarget
触发事件的对象:event.target (target不一定等于currentTarget,例如我点击按钮,但是事件绑定在按钮的父级,此时currentTarget就是按钮的父级,而target就是按钮) IE window.even.srcElement
event.type 触发的事件类型
例子:同一个函数绑定不同的事件
function fn(event) {
switch(event.type) {
case "click" : alert("click");break;
case "mousemove" : alert("mousemove");break;
case "mouseout" : alert("mouseout");break;
}
}
div.onclick = fn;
div.onmousemove = fn;
div.onmouseover = fn;
取消事件默认行为:event.preventDefault() IE window.event.returnValue = false
取消冒泡:event.stopPropagation() IE window.event.cancelBubble = true;
UI事件
load:当页面完全加载后(图片、JavaScript文件、CSS文件等)触发事件
unload:当页面完全卸载后触发事件
resize:当浏览器窗口调整大小(缩放)时触发
scroll:当滚动滚动条时触发
焦点事件
focus:在元素获得焦点时触发,不会冒泡
focusin:在元素获得焦点时触发,会冒泡; Firefox不支持
focusout:在元素失去焦点时触发,会冒泡; Firefox不支持
blur:在元素失去焦点时触发,不会冒泡;
判断是否支持这些事件:document.implementation.hasFeature("FocusEvent", "3.0");
鼠标与滚轮事件
mousedown:鼠标点击触发(不是键盘)
mouseup:释放鼠标按钮时触发
click:鼠标点击或按下回车键(只有mousedown和mouseup触发后,才会触发click)
dblclick:双击鼠标触发(只有click触发两次后才会触发,这里IE8及以下有bug,会跳过第二次mousedown和click事件)
mousemove:当鼠标指针在元素内部移动时重复触发
mouseout:当鼠标指针移出该元素时触发
mouseover:当鼠标首次进入该元素触发
下面两个IE、Firefox9+、Opera支持
mouseenter:鼠标光标从元素外部首次移动到元素内触发,移动到后代元素不会触发,不会冒泡
mouseleave:移出该元素触发,移动到后代元素不会触发,不冒泡
event.clientX和eventclientY:获取当前鼠标指针在视口中的水平和垂直坐标
event.pageX和event.pageY:获取当前鼠标指针在页面中的水平和垂直坐标(就是滚动出去的距离加上在视口的水平/垂直坐标,IE8及以下不支持,所以要计算,兼容代码在后面文章)
event.screenX和event,screenY:获取当前鼠标相对于电脑屏幕的坐标位置
event.shiftKey、event.ctrlKey、event.altKey和event.metaKey(在window是window键,在苹果机是cmd键,IE8及以下不支持):判断用户是否同时按下这些键
relatedTarget:获取mousemove和mouseout事件的相关元素(谁触发这个事件,那另外一个元素就是相关元素;就是比如,现在鼠标移出div进入body,div触发mouseout,相关元素就是body;同时,body触发mouseover,相关元素就是div)(IE不支持,但支持,mouseover:fromElement,mouseout:toElement)
判断鼠标按下了哪个键(左中右)
event.button,有三个值,0:表示鼠标左键,1:表示鼠标中键,2:表示鼠标右键
但是IE8及以下的值不一样:0:表示没有按下按钮,1:表示按下了左键,2:表示按下了右键,3:表示同时按下左右键,
4:表示按下中键,5:表示按下左键和中键,6:表示右键和中键,7:表示同时按下三键(真的是麻烦)
键盘与文本事件
keydown:按下键盘,如果一直按着,重复触发事件
keyup:释放键盘按键
keypress:按下字符键时触发,如果一直按着,重复触发事件
event.keyCode:按下键盘数字字母所对应的ASCII码(前提是触发了keydown和keyup事件)
event.charCode:获得触发onkeypress事件的按键所对应的ASCII编码
HTML5事件
contextmenu:右键,显示自定义上下文菜单(Opera11+,其他浏览器都支持)
下面是模仿JavaScript高级程序设计上的例子(我这里没有写兼容代码)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#my {
position: absolute;
visibility: hidden;
background-color: rgba(255,255,255,0.3);
width: 80px;
}
</style>
</head>
<body>
<div id="clickMe">click me</div>
<ul id="my">
<li><a href="http://www.baidu.com">baidu</a></li>
<li><a href="http://www.jd.com">jd</a></li>
<li><a href="http://www.taobao.com">taobao</a></li>
</ul>
<script>
document.getElementById("clickMe").oncontextmenu = function(e) {
e.preventDefault();
var my = document.getElementById("my");
my.style.left = event.clientX + "px";
my.style.top = event.clientY + "px";
my.style.visibility = "visible";
}
document.onclick = function () {
document.getElementById("my").style.visibility = "hidden";
}
</script>
</body>
</html>
beforunload:在浏览器卸载页面之前触发,就是关闭页面是就会触发这个事件,例如弹出一个对话框“真的要离开吗”
Opera11+,其他浏览器都支持
DOMContentLoaded:在load事件之前触发,不理会JavaScript文件、图片、CSS文件等是否加载完成。
IE9+、Firefox、Chrome、Safari3.1+、Opera9+支持
pageshow:在页面显示时触发,当重新加载页面是(后退、前进),pageshow会在load触发之后触发,必须用window绑定该事件
pagehide:在卸载页面是触发,在unload之前触发,必须用window绑定该事件
haschange:URL发生改变时触发,必须用window绑定该事件 IE8+、Firefox3.6+、Safari5+、Chrome、Opera10.6+
var newURL = location.href; var oldURL = location.hash
设备事件
设备转变方向:
IOS:window.orientation,0:表示正常,90:表示左旋转横向模式(头在左边),-90:表示右旋转横向模式(头在右边);同时还有个orientationchange事件,用window来绑定
(试验API)Macbook、Lenovo、Thinkpad、WindowsMobile、Android:MozOrientation事件,用window绑定,此时event会多出三个属性x,y,z(都是-1~1);默认0,0,1;向右倾斜x减少,接近用户方向y增大,z为垂直加速度1为静止0为失重
deviceorentation
devicemotion(先忽略这两个,以后再补)
(后面的移动端相关的先跳过)
事件委托
实际上就是利用冒泡,然后给它们公有的父元素绑定事件,然后判断是哪个元素(用event.target)触发事件
例子:(没有写兼容代码)
document.getElementById("allParent").onclick = function(e) {
var target = e.target;
switch(target.id) {
case "say" : alert("hi");break;
case "go" : alert("go go go");break;
case "back" : alert("go back");break;
}
}
如果按照之前的做法,一个一个的绑定,代码很多,占用内存就更多
移除事件处理程序
1.使用innerHTML代替页面某个部分时,此时如果带有事件处理函数的元素被innerHTML删除了,那么该事件处理程序极可能没有被回收,所以要在innerHTML之前解除绑定,例如btn.onclick = null;
2.还有就是,如果页面卸载之前没有清理干净事件处理程序,那么就会滞留在内存中(页面来回切换,或者刷新,内存中的对象就回增加),用onunload解绑所有事件处理程序
模拟事件(先跳过)