一、事件定义
- 关于事件实际上我们已经初步接触过了,指的就是用户与浏览器交互的一瞬间。
- 我们通过为指定事件绑定回调函数的形式来处理事 件,当指定事件触发以后我们的回调函数就会被调用,这样我们的页面就可以完成和用户的交互了。
- 这里还要更加深入的聊一聊事件的其他内容。
二、事件处理程序
• 我们可以通过两种方式为一个元素绑定事件处理程序:
- 通过HTML元素指定事件属性来绑定
- 通过DOM对象指定的属性来绑定
• 这两种方式都是我们日常用的比较多的,但是更推荐使 用第二种方式。
• 还有一种方式比较特殊我们称为设置事件监听器。使用 如下方式:
-元素对象.addEventListener()
2.1、通过HTML标签的属性设置
- 通过HTML属性来绑定事件处理程序是最简单的方式。
<button οnclick="alert('hello');alert('world')">按钮</button> |
- 这种方式当我们点击按钮以后,onclick属性中对应的JS代码将 会执行,也就是点击按钮以后,页面中会弹出两个提示框。
-
这种方式我们直接将代码编写到了onclick属性中,可以编写多 行js代码,当然也可以事先在外部定义好函数。
-
这种方式的优点在于,设定步骤非常简单,并且能够确保事件 处理程序会在载入时被设定。
-
如果在函数的最后return false则会取消元素的默认行为。
2.2、通过DOM对象的属性绑定
- 但是其实上面的写法虽然简单,但却将JS和HTML 的代码编写到了一起,并不推荐使用,我们更推荐 如下的写法:
var btn = document.getElementById('btn'); btn.onclick = function(){ |
-
这种写法将HTML代码和JS写在不同的位置,维护 起来更加容易。
三、设置事件的监听器
• 前边两种方式都可以绑定事件处理程序,但是它们都有一个缺 点就是都只能绑定一个程序,而不能为一个事件绑定多个程序。
• 这是我们就可以使用addEventListener()来处理,这个方法需 要两个参数:一个是事件字符串,一个是响应函数。
btn.addEventListener('click' , function(){alert("hello");}); |
• 但是要注意的是ie8以下的浏览器是不支持上边的方法的,需要 使用attachEvent代替。
• 也可以使用removeEventListener()和detachEvent()移除事件。
3.1、事件处理中的this
• 在事件处理程序内的 this 所引用的对象即是设定了该事件处理程序的元素。
• 也就是事件是给那个对象绑定的this就是哪个对象。
3.2、事件对象
-
在DOM对象上的某个事件被触发时,会产生一个 事件对象Event,这个对象中包含着所有事件有关 的信息。包括导致事件的元素、事件的类型以及其 他与特定事件相关的信息。
-
例如,鼠标操作导致的事件对象中,会包含鼠标位 置的信息,而键盘操作导致的事件对象中,会包含与按下的键有关的信息。所有浏览器都支持 event对象,但支持方式不同。
-
DOM标准的浏览器会将一个event对象传入到事件的处理程序 当中。无论事件处理程序是什么都会传入一个event对象。
-
可以通过这种方式获取:
btn.onclick = function(event){ alert(event.type);
};
-
Event对象包含与创建它的特定事件有关的属性和方法。触发 的事件类型不一样,可用的属性和方法也不一样。
3.3、Event对象的通用属性/方法
属性/方法 | 类型 | 读/写 | 说明 |
bubbles | Boolean | 只读 | 事件是否冒泡 |
cancelable | Boolean | 只读 | |
currentTarget | Element | 只读 | 当前正在处理的事件元素 |
defaultPrevented | Boolean | 只读 | 是否调用了preventDefault() |
detail | Number | 只读 | 与事件相关的细节信息 |
eventPhase | Number | 只读 | 阶段 1:捕获 2:目标 3:冒泡 |
preventDefault() | Function | 只读 | 取消事件的默认行为 |
stopImmediatePropagation() | Function | 只读 | |
stopPropagation() | Function | 只读 | |
target | Element | 只读 | 事件的目标 |
trusted | Boolean | 只读 | 是否是浏览器内置事件 |
type | String | 只读 | 被触发的事件的类型 |
3.4、IE中的事件对象
-
与访问DOM中的event对象不同,要访问IE中 的 event 对象有几种不同的方式,取决于指定事件 处理程序的方法。
- 在IE中event对象作为window对象的属性存在的, 可以使用window.event来获取event对象。
- 在使用attachEvent()的情况下,也会在处理程序中 传递一个event对象,也可以按照前边的方式使用。
3.5、Event对象的通用属性/方法
属性/方法 | 类型 | 读/写 | 说明 |
cancelBubble | Boolean | 读/写 | 是否取消冒泡 |
returnValue | Boolean | 读/写 | 是否执行默认行为 |
srcElement | Element | 只读 | 事件的目标 |
type | String | 只读 | 被触发的事件的类型 |
四、事件的触发
-
事件的发生主要是由用户操作引起的。
-
比如mousemove这个事件就是由于用户移动鼠标引起的,在鼠标指针移动的过程中该事件会持续发生。
-
当指定事件被触发时,浏览器就会调用对应的函数去响 应事件,一般情况下事件没触发一次,函数就会执行一 次。
-
因此设置鼠标移动的事件可能会影响到鼠标的移动速度。 所以设置该类事件时一定要谨慎。
4.1、事件的传播
• 在网页中标签与标签之间是有嵌套关系的,比如这样一个页面:
<html> <body> <div id="foo"> </div> </body> </html> |
• 如果这时用户点击了sample按钮,则会以该按钮作为事件目标触发一次点击事件。
• 这时,事件的处理将会分为捕获阶段、目标阶段、事件冒泡这三个阶段。
4.2、事件的传播流程
• 捕获阶段
– 这一阶段会从window对象开始向下一直遍历到目标对象,如果发现有对象绑定了响应事件则做相应的处理。
• 目标阶段
– 这一阶段已经遍历结束,则会执行目标对象上绑定的响应函数。
• 事件冒泡阶段
– 这一阶段,事件的传播方式和捕获阶段正好相反,会从事件目标一直向 上遍历,直至window对象结束,这时对象上绑定的响应函数也会执行。
4.3、取消事件传播
• 我们可以使用event对象的两个方法完成:
– stopPropagation()
– stopImmediatePropagation()
• 取消默认行为:
– preventDefault()
五、常用简单例子
5.1、事件冒泡
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> #box1{ width: 200px; height: 200px; background-color: yellowgreen; } #s1{ background-color: yellow; } </style> <script type="text/javascript"> window.onload = function(){ /* * 事件的冒泡(Bubble) * - 所谓的冒泡指的就是事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发 * - 在开发中大部分情况冒泡都是有用的,如果不希望发生事件冒泡可以通过事件对象来取消冒泡 */ //为s1绑定一个单击响应函数 var s1 = document.getElementById("s1"); s1.onclick = function(event){ event = event || window.event; alert("我是span的单击响应函数"); //取消冒泡 //可以将事件对象的cancelBubble设置为true,即可取消冒泡 // event.cancelBubble = true; }; //为box1绑定一个单击响应函数 var box1 = document.getElementById("box1"); box1.onclick = function(event){ event = event || window.event; alert("我是div的单击响应函数"); // event.cancelBubble = true; }; //为body绑定一个单击响应函数 document.body.onclick = function(){ alert("我是body的单击响应函数"); }; }; </script> </head> <body> <div id="box1"> 我是box1 <span id="s1">我是span</span> </div> </body> </html> |
效果:
当点击子结点对象时其所有父节点都触发事件。
5.2、事件的绑定
/* * 参数: * obj 要绑定事件的对象 * eventStr 事件的字符串(不要on) * callback 回调函数 */ function bind(obj , eventStr , callback){ if(obj.addEventListener){ //大部分浏览器兼容的方式 obj.addEventListener(eventStr , callback , false); }else{ /* * this是谁由调用方式决定 * callback.call(obj) */ //IE8及以下 obj.attachEvent("on"+eventStr , function(){ //在匿名函数中调用回调函数 callback.call(obj); }); } } |
调用:
bind(btn01 , "click" , function(){ alert(this); }); |
5.3、事件的拖拽
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> #box1{ width: 100px; height: 100px; background-color: red; position: absolute; } #box2{ width: 100px; height: 100px; background-color: yellow; position: absolute; left: 200px; top: 200px; } </style> <script type="text/javascript"> window.onload = function(){ /* * 拖拽box1元素 * - 拖拽的流程 * 1.当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown * 2.当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove * 3.当鼠标松开时,被拖拽元素固定在当前位置 onmouseup */ //获取box1 var box1 = document.getElementById("box1"); //为box1绑定一个鼠标按下事件 //当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown box1.onmousedown = function(event){ event = event || window.event; //div的偏移量 鼠标.clentX - 元素.offsetLeft //div的偏移量 鼠标.clentY - 元素.offsetTop var ol = event.clientX - box1.offsetLeft; var ot = event.clientY - box1.offsetTop; //为document绑定一个onmousemove事件 document.onmousemove = function(event){ event = event || window.event; //当鼠标移动时被拖拽元素跟随鼠标移动 onmousemove //获取鼠标的坐标 var left = event.clientX - ol; var top = event.clientY - ot; //修改box1的位置 box1.style.left = left+"px"; box1.style.top = top+"px"; }; //为document绑定一个鼠标松开事件 document.onmouseup = function(){ //当鼠标松开时,被拖拽元素固定在当前位置 onmouseup //取消document的onmousemove事件 document.onmousemove = null; //取消document的onmouseup事件 document.onmouseup = null; }; }; }; </script> </head> <body> <div id="box1"></div> <div id="box2"></div> </body> </html> |
效果:
鼠标按下红色方块能拖动。
5.5、滚轮事件
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> #box1{ width: 100px; height: 100px; background-color: red; } </style> <script type="text/javascript"> window.onload = function(){ //获取id为box1的div var box1 = document.getElementById("box1"); //为box1绑定一个鼠标滚轮滚动的事件 /* * onmousewheel鼠标滚轮滚动的事件,会在滚轮滚动时触发, * 但是火狐不支持该属性 * 在火狐中需要使用 DOMMouseScroll 来绑定滚动事件 * 注意该事件需要通过addEventListener()函数来绑定 */ box1.onmousewheel = function(event){ event = event || window.event; //event.wheelDelta 可以获取鼠标滚轮滚动的方向 //向上滚 120 向下滚 -120 //wheelDelta这个值我们不看大小,只看正负 //alert(event.wheelDelta); //wheelDelta这个属性火狐中不支持 //在火狐中使用event.detail来获取滚动的方向 //向上滚 -3 向下滚 3 //alert(event.detail); /* * 当鼠标滚轮向下滚动时,box1变长 * 当滚轮向上滚动时,box1变短 */ //判断鼠标滚轮滚动的方向 if(event.wheelDelta > 0 || event.detail < 0){ //向上滚,box1变短 box1.style.height = box1.clientHeight - 10 + "px"; }else{ //向下滚,box1变长 box1.style.height = box1.clientHeight + 10 + "px"; } /* * 使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false * 需要使用event来取消默认行为event.preventDefault(); * 但是IE8不支持event.preventDefault();这个玩意,如果直接调用会报错 */ event.preventDefault && event.preventDefault(); /* * 当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动, * 这是浏览器的默认行为,如果不希望发生,则可以取消默认行为 */ return false; }; //为火狐绑定滚轮事件 bind(box1,"DOMMouseScroll",box1.onmousewheel); }; function bind(obj , eventStr , callback){ if(obj.addEventListener){ //大部分浏览器兼容的方式 obj.addEventListener(eventStr , callback , false); }else{ /* * this是谁由调用方式决定 * callback.call(obj) */ //IE8及以下 obj.attachEvent("on"+eventStr , function(){ //在匿名函数中调用回调函数 callback.call(obj); }); } } </script> </head> <body style="height: 2000px;"> <div id="box1"></div> </body> </html> |
效果:
当鼠标进入红色方块,鼠标向上滚向上滚,box1变短,反之变长。当然,Mac系统正好相反。
5.6、键盘事件
/* * 键盘事件: * onkeydown * - 按键被按下 * - 对于onkeydown来说如果一直按着某个按键不松手,则事件会一直触发 * - 当onkeydown连续触发时,第一次和第二次之间会间隔稍微长一点,其他的会非常的快 * 这种设计是为了防止误操作的发生。 * onkeyup * - 按键被松开 * 键盘事件一般都会绑定给一些可以获取到焦点的对象或者是document */ document.onkeydown = function(event){ event = event || window.event; /* * 可以通过keyCode来获取按键的编码 * 通过它可以判断哪个按键被按下 * 除了keyCode,事件对象中还提供了几个属性 * altKey * ctrlKey * shiftKey * - 这个三个用来判断alt ctrl 和 shift是否被按下 * 如果按下则返回true,否则返回false */ //console.log(event.keyCode); //判断一个y是否被按下 //判断y和ctrl是否同时被按下 if(event.keyCode === 89 && event.ctrlKey){ console.log("ctrl和y都被按下了"); } }; |
效果:
同时按下ctrl+y在控制台打印: