版权声明:本文为博主原创文章,若文章中有错误请联系博主改正,请不要恶意留言(不喜欢请绕道)。欢迎大家转载,转载时请注明原文地址:https://blog.csdn.net/qq_37674616/article/details/82470350
目录
事件
事件,就是文档或浏览器窗口中发生的一些特定交互瞬间。
事件的三要素
事件目标
事件处理程序
事件对象
例如 btn.function(event){} 对该用事件来代码分析,则 btn为事件目标 ,事件处理程序为 function函数, 事件对象 event
事件流
事件流描述的是从页面中接收事件的顺序。事件流可分为冒泡事件流和捕获事件流。
冒泡事件流
该事件流又称IE事件流,该事件流是从内向外传播(即逐级向上传播)
下图此时事件会按照如下顺序传播:
handle1 -->handle2 -->handle3 -->handle4
<html>
<head>
<title></title>
</head>
<body>
<div id="myDiv">Click Me</div>
</body>
</html>
<script>
div.onclick=handle1;
body.onclick=handle2;
html.onclick=handle3;
document.onclick=handle4;
function handle1(){}
function handle2(){}
....
</script>
捕获事件流
该事件流又称NetScape Communicator(网景).
思想:是不太具体的节点应该更早接受到事件,而最具体的节点应该最后接受到事件。即事件是从外到内传播
此时事件会按照如下顺序传播:
handle4 -->handle3 -->handle2 -->handle1
<html>
<head>
<title></title>
</head>
<body>
<div id="myDiv">Click Me</div>
</body>
</html>
<script>
div.onclick=handle1;
body.onclick=handle2;
html.onclick=handle3;
document.onclick=handle4;
function handle1(){}
function handle2(){}
....
</script>
DOM事件流
该事件分三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首先从事件捕获阶段开始,然后到实际的目标接受事件,最后为事件冒泡阶段。
事件处理程序
DOM0级事件处理程序
该处理程序不存在兼容性问题。
缺点:
1.是要等待html页面加载完毕后才能操作
2.只能添加一个事件处理程序(会覆盖)
形式:
var btn=document.getElementById('myBtn');
btn.onclick=function(){
console.log('我不会被执行');
}
btn.onclick=function(){
console.log(this.id); //"myBtn"
}
//删除绑定
btn.onclick=null;
**:DOM0级中的this指向调用者即事件目标
DOM2级事件处理程序
该事件处理程序存在兼容性问题,一般分为IE8版以下和非IE8版本以下
优点:可以添加多个事件处理函数(执行顺序有差异的区别对待)
非IE8版本以下
定义两个方法用于处理指定和删除事件程序:addEventListener()和removeEventListener().
addEventListener(type,handle,boolean)
参数
type:要处理事件的事件名
handle:事件处理的函数
boolean:true/false
true表示在捕获阶段调用事件处理程序,false表示在冒泡阶段调用处理程序。默认为false
removeEventListener(type,handle,boolean)
参数
type:要处理事件的事件名
handle:事件处理的函数
boolean:true/false
true表示在捕获阶段调用事件处理程序,false表示在冒泡阶段调用处理程序。默认为false
事件执行顺序
var btn=document.getElementById('myBtn');
btn.addEventListener('click',function(){
console.log(this.id);
});
btn.addEventListener('click',function(){
console.log("hello");
});
**:从上到下执行顺序执行即先打印ID然后"hello";
匿名函数不能解绑事件
var btn=docuemnt.getElementById('myBtn');
btn.addEventListener('click',function(){
console.log(this.id);
});
btn.removeEventListener('click',function(){ //没有用!
console.log('事件被移除');
});
**:因为两个匿名函数在堆内存中的地址不一样所以无法解除绑定。因此我们要将函数的引用传入给事件处理函数,这样才能解除绑定。
function handle(){
console.log(this.id);
}
var btn=docuemnt.getElementById('myBtn');
btn.addEventListener('click',handle);
btn.removeEventListener('click',handle);
IE8版本以下
对以该版本对于事件处理程序提供:attachEvent()、detachEvent()。这两个方法接受相同的两个参数:事件处理程序名称和事件处理程序函数。
var btn=document.getElementById('MyBtn');
btn.attachEvent('onclick',function(){
console.log(this===window); //true
});
**:IE8以下用DOM2级绑定事件this指向window
事件执行顺序
btn.attachEvent('onclick',function(){
console.log('click');
});
btn.attachEvent('onclick',function(){ //先被执行
console.log("hello");
});
**:事件处理是以相反顺序执行即先打印"hello"然后打印"click"。
解除绑定
同样如果函数是以匿名函数写入则不能解除绑定。
var btn=document.getElementById('MyBtn');
btn.attachEvent('onclick',handle);
//解除绑定
btn.detachEvent("onclick",handle);
对于事件程序兼容处理
<script>
var util = {
//绑定事件
band: function(element, type, handle) {
if (element.addEventListener) {
element.addEventListener(type, handle, false);
} else if (element.attachEvent) {
//IE8以下版本
element.attachEvent("on" + type, handle);
} else {
//兜底
element['on' + type] = handle;
}
},
//解除绑定
unband: function(element, type, handle) {
if (element.removeEventListener) {
element.removeEventListener(type, handle, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handle);
} else {
element["on" + type] = null;
}
}
};
var btn = document.getElementById('myBtn');
util.band(btn, 'click', handle);
function handle() {
console.log(this.id);
}
</script>
事件对象
非IE8以下
属性
currentTarget 表示当前正在处理事件的那个元素
target 事件的目标
type 被触发的事件类型
detail 与事件相关的细节信息
eventPhase 调用事件处理程序的阶段:1 表示捕获阶段,2 表示"处于目标" 3 表示冒泡阶段
方法
preventDefault()
只读属性。取消事件的默认行为
示例
我们可以阻止a链接的默认行为(即点击后会导航到指定url)
var link=document.getElementById('myLink');
link.onclick=function(event){
event.preventDefault();
}
stopPropagation()
只读属性。取消冒泡事件或捕获
示例
<html>
<head>
<title></title>
</head>
<body>
<div id="myDiv">Click Me</div>
</body>
</html>
<script>
div.onclick=handle1;
body.onclick=handle2;
function handle1(event){
console.log('div');
//阻止,冒泡事件的传播
event.stopPagation();
}
function handle2(){
console.log('body'); //不会打印
}
</script>
IE8以下
事件对象的不同
在DOM0级事件处理程序中
event对象作为window对象中的一个属性存在
var btn=document.getElementById('myBtn');
btn.onclick=function(){
var event=window.event;
console.log(event.type);
}
在DOM2级事件处理程序中
event对象作为参数被传入事件处理程序函数。
var btn=document.getElementById('myBtn');
btn.attachEvent("onclick",function(event){
console.log(event.type);
});
属性
srcElement
只读属性。事件的目标(与target属性相同)
type
只读属性。被触发的事件类型
方法
cancelBubble(true/false)
可读可写。默认值为false,true取消事件冒泡
示例
<html>
<head>
<title></title>
</head>
<body>
<div id="myDiv">Click Me</div>
<script>
div.onclick=handle1;
body.onclick=handle2;
function handle1(){
console.log('div');
//阻止,冒泡事件的传播
window.event.cancelBubble=true;
}
function handle2(){
console.log('body'); //不会打印
}
</script>
</body>
</html>
returnValue(true/false)
可读可写。默认是true,设置为false表示取消事件的默认行为。
var link=document.getElementById('myLink');
link.onclick=function(){
window.event.returnValue=false;
}
浏览器兼容处理
<body>
<button id="myBtn">点击我</button>
<script>
var util = {
//获取对象事件
getEvent: function(event) {
return event ? event : window.event;
},
//获取事件源
getTarget: function(event) {
return event.target || event.srcElement;
},
//阻止默认行为
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
//阻止冒泡或捕获
stopPropagation: function(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.canceBubble = true;
}
}
};
var btn = document.getElementById('myBtn');
btn.onclick = function(event) {
console.log('btn');
//获取事件对象
event = util.getEvent(event);
util.stopPropagation(event);
}
document.body.onclick = function() {
console.log('body'); //不会打印
}
</script>
</body>
事件委托
事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
案例:当鼠标移入li时给给li添加背景移除时背景移除。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>鼠标移入移出背景变化</title>
<link rel="stylesheet" href="">
<style>
#list {
padding: 0;
list-style: none;
border: 1px solid black;
overflow: hidden;
}
li {
margin: 10px;
width: 100px;
height: 100px;
border: 1px solid black;
display: inline-block;
}
</style>
<script>
var util = {
getEvent: function(event) {
return event ? event : window.event;
},
getTarget: function(event) {
return event.target ? event.target : event.srcElement;
}
}
window.onload = function() {
var ul = document.getElementById('list');
//鼠标移入事件
ul.onmouseover = function(event) {
//获取事件对象
var event = util.getEvent(event);
//获取事件源
var target = util.getTarget(event);
if (target.nodeName == "LI") {
//改变选中的li背景
target.style.background = 'orange';
}
}
//鼠标移出事件
ul.onmouseout = function() {
var event = util.getEvent(event);
var target = util.getTarget(event);
if (target.nodeName == "LI") {
target.style.background = '';
}
}
}
</script>
</head>
<body>
<ul id="list">
<li></li>
<li></li>
<li></li>
</ul>
</body>
</html>
**:如果这个案例我们给li绑定鼠标事件,就需要给所有li绑定那么页面会多次渲染就算我们不点击也会这样做。而且如果我们给ul追加子节点时该要加鼠标事件。这些问题事件委托就能帮我们很好的解决。
事件类型
UI事件
该事件指的是不一定与用户操作有关的事件
load
当页面完全加载后在window上面触发,当所有框架都加载完时在框架上触发,当图片加载完毕时在<img>元素上触发,当嵌入的内容加载完毕时在<object>元素上面触发
unload
当页面完全卸载后在window上面触发.当所有框架都卸载后在框架上面触发
select
当用户选择文本框中的一或多个字符时触发
resize
当窗口或框架的大小变化时在window或框架上面触发
scroll
当页面滚动带滚动条的元素中的内容时,在该元素上面触发。
焦点事件
焦点事件会在页面元素获取或失去焦点时触发。
blur
在元素失去焦点时触发。这个事件不会冒泡
focus
在元素获取焦点是触发。这个事件不会冒泡
focusin
在元素获取焦点时触发。这个事件与focus等价但会冒泡
focusout
在元素失去焦点时触发。这个事件与blur等价。
鼠标事件
click
用户单击鼠标按键或按下回车键时触发。
dbclick
在用户双击主鼠标按钮时触发
mousedown
在用户按下任意鼠标按钮时触发。
mouseup
在用户抬起鼠标按钮时触发
mouseenter
在鼠标从元素外部首次进入到元素之内时触发,这个事件不会冒泡,而且在光标移动到后代元素时不会触发
mouseleave
在位于元素上的鼠标光标移动到元素范围之外时触发。这个事件不会冒泡,而且在光标移动到后代元素上不会触发
mousemove
当鼠标指针在元素内部移动时重复触发,支持冒泡
mousemove
当鼠标指针位于一个元素上方,然后移动出该元素时触发。支持冒泡
mouseover
当鼠标位指针位于一个元素外部,然后用户将其首次移入另一个元素边界之内时触发。支持冒泡
坐标属性
视口坐标
clientX
clientY
页面坐标
pageX
pageY
屏幕坐标
screenX
screenY
**:当页面不滚动时视口坐标与页面坐标相等
滚动事件
mousewheel
该事件IE、Opera、Chrome和Safari都实现了。
wheelDelta
该属性可以检测用户鼠标是前滚动还是后滚动。wheelDelta是120的倍数.当用户向前滚动时是正120的倍数、向后滚动时是-120的倍数。
**:如果在Opera9.5版本之前,wheelDelta的值的正负号是颠倒的。
DOMMouseScroll
该事件只有火狐支持,而且不支持DOM0级绑定该属性。在滚动信息中保存在detail属性中。当鼠标向前滚动时,这个属性的值是-3的倍数。向后滚动时是3的倍数。
滚动事件的兼容
我们将前面事件兼容的工具方法整理到一起:
var util = {
//绑定事件的方法
band: function(ele, type, handle) {
//元素 类型 事件函数
if (ele.addEventListener) {
ele.addEventListener(type, handle);
} else if (ele.attachEvent) {
ele.attachEvent('on' + type, handle);
} else {
ele['on' + type] = handle;
}
},
//解绑
unband: function(ele, type, handle) {
if (ele.removeEventListener) {
ele.removeEventListener(type, handle);
} else if (ele.detachEvent) {
ele.detachEvent('on' + type, handle);
} else {
ele['on' + type] = null;
}
},
//event对象
getEvent: function(event) {
return event = event ? event : window.event;
},
//冒泡
stopPropagation: function(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
//IE及以下阻止冒泡
event.cancelBubble = false;
}
},
//阻止默认
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
//事件源
getTarget: function(event) {
return event.target ? event.target : event.srcElement;
},
//获取滚动值
getWheelDelta: function(event) {
if (event.wheelDelta) {
return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);
} else {
return -event.detail * 40;
}
}
}
下面我们来写测试上面鼠标滚动的兼容性:
<script>
var client = function() {
var engine = {
//呈现引擎
ie: 0,
gecko: 0,
webkit: 0,
khtml: 0,
opera: 0,
//具体版本号
ver: null
};
return {
engine: engine
};
}();
util.band(document, 'mousewheel', scroll);
util.band(document, 'DOMMouseScroll', scroll);
function scroll(event) {
var event = util.getEvent(event);
if (util.getWheelDelta(event) > 0) {
console.log('向前走');
} else {
console.log('向后走');
}
}
</script>
文本事件
textInput
当用户在可编辑区域中输入字符是,就会触发这个事件。支持该属性的浏览器有IE9+、Safari和Chrome(测试只时IE11不支持该属性)
测试:
<script>
var input=document.getElementById('myText');
util.band(input,'textInput',function(event){
var event=util.getEvent(event);
alert(event.data);
});
</script>
**:上面的代码都用到了工具方法请先导入该工具对象。
键盘事件
keydown
当用户按下键盘上的任意键时触发,而且如果按住不放会重复触发此事件。
keypress
当用户按下键盘上的字符键时触发,而且如果按住不放的话会重复触发
keyup
当用户释放键盘上的键时触发
键码
在发生keydown和keyup事件时,event对象的KeyCode属性中会包含一个代码与键盘上一个特定的键对应