load事件
当页面完全加载后再window上面触发,当所有框架都加载完成时,在框架集上面触发,当图片都加载完成时在img标签上面触发,或者当嵌入的内容加载完成时在object上触发。
unload事件
和load事件恰好相反,除img标签外,其他的框架和嵌入内容卸载完毕后在对应的级别上触发。
abort事件
在用户停止下载过程时,如果嵌入的内容没有加载完毕,在object元素上线触发。
error事件
当js发生语法错误时在window上触发,当发生加载图像无法成功时在img标签上触发,当嵌入的内容无法加载时在object元素上触发,或当一个或多个框架无法加载完成时在框架集上面触发。
select事件
当用户选择文本框内的文字时触发(input或textarea)。
resize事件
当窗口或者框架的大小变化时在window或框架上面触发。
scroll事件
当用户滚动带有滚动条的元素中的内容时,在该元素上面触发。body上就是网页自带的滚动条。
对于文档嵌入内容不是很清楚的同学可以去看一下HTML5权威指南的第15章节内容。
blur事件、focusout
输入框失去焦点事件,css有相同伪类选择器,但是不够灵活!
focusin事件、focus
输入框获取焦点是触发,同样,css有相同的伪类事件。输入框如果使用 click同样能获取焦点,但是有点牛头马嘴的意思。
focus和blur事件不支持冒泡,如果不想文档事件冒泡则使用这两个事件更好,不用屏蔽事件流。
mousedown、mouseup事件
鼠标左键按下、抬起事件,相继触发这两个事件后还会触发click事件。
click事件、dbclick事件
鼠标单击、双击事件
mouseleave、mouseout事件
都是鼠标脱离当前区域触发,不同的是mouseleave不冒泡。
mouseenter、mouseover事件
鼠标进入、悬停在当前区域时触发,mouseenter事件不冒泡。
mousemove事件
当鼠标在当前区域移动时重复触发!
mousewheel事件
滚轮事件在鼠标中间滚动时触发,同时包含一个wheelData属性,它是120的整数倍数,滚轮向上滚动一个单位时wheelDate+120,向下滚动时-120,。
<body>
<input type="text" id="test">
</body>
<script>
/* 虽然id可以直接拿来使用,但是并不提倡,这不符合规范! */
test.onkeypress=function(event){ //event是系统默认传递的事件对象
console.log(event.keyCode); //输出键码
console.log(test.value); //输出input值
};
</script>
在我依次按下数字键1、2、3、4、5、6时控制台是如下效果:
index.html:15 49
index.html:16
index.html:15 50
index.html:16 1
index.html:15 51
index.html:16 12
index.html:15 52
index.html:16 123
index.html:15 53
index.html:16 1234
index.html:15 54
index.html:16 12345
但是如果是keyup的事件呢:
在我依次按下数字键1、2、3、4、5、6时控制台是如下效果:
index.html:15 49
index.html:16 1
index.html:15 50
index.html:16 12
index.html:15 51
index.html:16 123
index.html:15 52
index.html:16 1234
index.html:15 53
index.html:16 12345
index.html:15 54
index.html:16 123456
根据网页文档的DOM级别规定层级结构:
文档结构 |
---|
document |
html |
body |
element |
假定事件在element上触发,然后事件会跟着下图一次冒泡
graph LR
Element-->body
body-->html
html-->document
事件是默认冒泡的,在IE9,Opera9.5及其他浏览器各版本及更高版本都是支持事件流的,但是上述明确浏览器的更低版本则不支持。
控制台输出的结果:
index.html:29
index.html:26 …
index.html:23 ……
index.html:20 #document
index.html:17 Window{postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window,…}
如果我们把this全价格toString方法改为字符串!
index.html:29 [object HTMLDivElement]
index.html:26 [object HTMLBodyElement]
index.html:23 [object HTMLHtmlElement]
index.html:20 [object HTMLDocument]
index.html:17 [object Window]
同事件冒泡正好相反,它会按照事件流向下级结构传递:
graph LR
document-->html
html-->body
body-->element
而控制他们事件流传递方向的创建事件监听时的一个参数,后面我再详细解释。
testElement.addEventListener("click",function(event) {
console.log(this);
console.log(event.type);
},false);
/*
index.html:32
index.html:33 click
*/
它的第三个参数默认为false,代表默认使用事件冒泡规则,同时事件会根据冒泡规则一次向上传递,如果改为true则事件采用事件捕获规则,根据文档结构和元素关系进行事件的向下传递。
testElement.removeEventListener("click",function(event) {
console.log(this);
console.log(event.type);
},false);
但是我们要注意的地方是,事件移除程序移除的是第二参数传递进去的函数,如果是函数体,会因为指向问题使移除监听并不算成功,而我们如果传递进去的是函数名的话,则能很好的达到效果!没听懂,没关系,看下面:
testElement.addEventListener("click",function(event) { //它没有被取消掉
console.log(this);
console.log(event.type);
},false);
testElement.removeEventListener("click",function(event) { //它没有效果
console.log(this);
console.log(event.type);
},false);
/*
index.html:32
index.html:33 click
*/
没错,remove里的没有执行,但是add里的却仍然很好的执行了!那我们来看正确的方式!
testElement.addEventListener("click", handler, false);
testElement.removeEventListener("click", handler, false);
function handler(event) {
console.log(this)
console.log(event.type);
}
/*
控制台你什么也不会看到!
*/
究其原因,是因为上面的创建和移除是各自创建的函数,它们看起来很像,但是根本没有丝毫"血缘"关系,它们在内存中占据了两个不同的位置,而后面引用的函数名确实代表的同一个"东西",它们指向的是内存中的同一个位置!!!
/*
index.html:29
index.html:30 click
*/
如果要测试事件捕获需要用规范的创建事件监听,并使第三个参数改为true就可以了!
阻止默认行为发生
说到默认行为,就像a标签点击了会默认跳转到href一样,那么我们可以通过使用preventdefault()方法实现,但是前提条件是对象的属性cancelable属性必须设置为true才可以阻止该对象的默认行为,使用时同时用event对象来调用!大家可以自行测试,这里就不赘述了。
var EventUtil = {
addHandler: function (ele, type, handler) {
if (ele.addEventListener) {
ele.addEventListener(type, handler, false);
} else if (ele.attachEvent) {
ele.attachEvent("on" + type, handler);
} else {
ele["on" + type] = handler;
}
},
removeHandler: function (ele, type, handler) {
if (ele.removeEventListener) {
ele.removeEventListener(type, handler, false);
} else if (ele.detachEvent) {
ele.detachEvent("on" + type, handler);
} else {
ele["on" + type] = null;
}
},
getEvent: function (event) {
return event ? event : window.event; //低版本IE的event对象位置不同!
},
getTarget: function (event) {
return event.target || event.srcElement;//不同浏览器有不同的调取方法
},
preventDefault: function (event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.retrunValue = false;
}
},
stopPropagation:function(event){
if(event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble();
}
}
};
//比如创建一个键盘监听事件
EventUtil.addHandler(document, "keyup", function (event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
KeyUp(target, event.keyCode ? event.keyCode.toString() : "mouse");
});
/*
事件处理程序创建了一个键盘监听事件,通过EventUtil对象的getEvent获取当前事件,然后通过event的特有属性,
event.target获取到事件触发时的响应目标(直接获取到元素对象!),然后通过参数等调用相应需要实现的函数
*/
EventUtil.addHandler(document, "keyup", function (event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
KeyUp(target, event.keyCode ? event.keyCode.toString() : "mouse");
});