js 事件
Posted 浅唱年华1920
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js 事件相关的知识,希望对你有一定的参考价值。
javascript 与 html 之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些 特定的交互瞬间。可以使用侦听器(或处理程序)来预订事件,以便事件发生时执行相应的代 码。这种在传统软件工程中被称为观察员模式的模型,支持页面的行为(JavaScript 代码)与页面的外观(HTML 和 CSS 代码)之间的松散耦合。
1. 事件流
事件流描述的是从页面中接收事件的顺序。
2.事件冒泡
IE 的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深 的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
3.事件捕获
Netscape Communicator 团队提出的另一种事件流叫做事件捕获(event capturing)。事件捕获的思想 是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在 事件到达预定目标之前捕获它。
4.DOM事件流
“DOM2级事件”规定的事件流包括三个阶段: 事件捕获阶段、处于目标阶段 和 事件冒泡阶段。首 先发生的是事件捕获,为截获事件提供了机会。然后是实际的目标接收到事件。最后一个阶段是冒泡阶 段,可以在这个阶段对事件做出响应。
5.事件绑定
(1)
<button onclick="test()">按钮</button> function test(){ console.log(\'点击事件\'); }
(2)
var btn = document.getElementById("myBtn"); btn.onclick = function(){ alert("Clicked"); };
btn.onclick = null; //删除事件处理程序
(3)
“DOM2 级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener() 和 removeEventListener()。所有 DOM 节点中都包含这两个方法,并且它们都接受 3 个参数:要处 理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是 true,表示在捕获 阶段调用事件处理程序;如果是 false,表示在冒泡阶段调用事件处理程序。
var btn = document.getElementById("myBtn"); var handler = function(){ alert(this.id); }; btn.addEventListener("click", handler, false); btn.removeEventListener("click", handler, false); //移除事件
IE 实现了与 DOM 中类似的两个方法:attachEvent()和 detachEvent()。这两个方法接受相同 的两个参数:事件处理程序名称与事件处理程序函数。由于 IE8 及更早版本只支持事件冒泡,所以通过 attachEvent()添加的事件处理程序都会被添加到冒泡阶段。
var btn = document.getElementById("myBtn"); var handler = function(){ alert("Clicked"); }; btn.attachEvent("onclick", handler); //移除事件 btn.detachEvent("onclick", handler);
6.跨浏览器的事件处理程序
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; } } };
var btn = document.getElementById("myBtn"); var handler = function(){ alert("Clicked"); }; EventUtil.addHandler(btn, "click", handler); EventUtil.removeHandler(btn, "click", handler); //移除事件
7. DOM中的事件对象
兼容 DOM 的浏览器会将一个 event 对象传入到事件处理程序中。无论指定事件处理程序时使用什么方法(DOM0 级或 DOM2 级),都会传入 event 对象。
var btn = document.getElementById("myBtn"); btn.onclick = function(event){
alert(event.type); //"click" }; btn.addEventListener("click", function(event){ alert(event.type); //"click"
}, false);
事件对象属性:
在事件处理程序内部,对象 this 始终等于 currentTarget 的值,而 target 则只包含事件的实 际目标。如果直接将事件处理程序指定给了目标元素,则 this、currentTarget 和 target 包含相同 的值。来看下面的例子。
var btn = document.getElementById("myBtn"); btn.onclick = function(event){ alert(event.currentTarget === this); //true alert(event.target === this); //true alert(event.target === document.getElementById("myBtn"));//true };
要阻止特定事件的默认行为,可以使用 event.preventDefault() 方法。
event.stopPropagation() 方法用于立即停止事件在 DOM 层次中的传播,即取消进一步的事件 捕获或冒泡
事件对象的 eventPhase 属性可以用来确定事件当前正位于事件流的哪个阶段。
捕获阶段 : 1
目标阶段:2
冒泡阶段: 3
var btn = document.getElementById("myBtn"); btn.onclick = function(event){ alert(event.eventPhase); //2 }; document.body.addEventListener("click", function(event){ alert(event.eventPhase); //1 }, true); document.body.onclick = function(event){ alert(event.eventPhase); //3 };
ps: 只有在事件处理程序执行期间,event 对象才会存在;一旦事件处理程序执行完 成,event 对象就会被销毁。
8. IE中的事件对象
与访问 DOM 中的 event 对象不同,要访问 IE 中的 event 对象有几种不同的方式,取决于指定事 件处理程序的方法。
var btn = document.getElementById("myBtn"); btn.onclick = function(){ var event = window.event; alert(event.type); //"click" };
在此,我们通过 window.event 取得了 event 对象,并检测了被触发事件的类型(IE 中的 type 属性与 DOM 中的 type 属性是相同的)。可是,如果事件处理程序是使用 attachEvent()添加的,那 么就会有一个 event 对象作为参数被传入事件处理程序函数中,如下所示。
var btn = document.getElementById("myBtn"); btn.attachEvent("onclick", function(event){
alert(event.type); //"click" });
在像这样使用 attachEvent()的情况下,也可以通过 window 对象来访问 event 对象,就像使用 DOM0 级方法时一样。
事件对象属性:
因为事件处理程序的作用域是根据指定它的方式来确定的,所以不能认为 this 会始终等于事件目 标。故而,最好还是使用 event.srcElement 比较保险。例如
var btn = document.getElementById("myBtn"); btn.onclick = function(){ alert(window.event.srcElement === this); //ture }; btn.attachEvent("onclick", function(event){ alert(event.srcElement === this); //true });
returnValue 属性相当于 DOM 中的 preventDefault()方法,它们的作用都是取消 给定事件的默认行为。只要将 returnValue 设置为 false,就可以阻止默认行为。
相应地,cancelBubble 属性与 DOM 中的 stopPropagation()方法作用相同,都是用来停止事 件冒泡的。由于 IE 不支持事件捕获,因而只能取消事件冒泡;
但 stopPropagatioin() 可以同时取消事件捕获和冒泡。
var btn = document.getElementById("myBtn"); btn.onclick = function(){ alert("Clicked"); window.event.cancelBubble = true; //阻止事件冒泡 };
9. 跨浏览器的事件对象
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; } }, // 事件对象 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; } }, //移除事件 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; } }, //阻止事件冒泡 捕获 stopPropagation: function(event) { if(event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; } }, //获取滚动条滚动的值 getWheelDelta: function(event){ if (event.wheelDelta){ return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta); } else { return -event.detail * 40; } }, //获取键盘码 getCharCode: function(event){ if (typeof event.charCode == "number"){ return event.charCode; } else { return event.keyCode; } }, }
示例:
btn.onclick = function(event){ event = EventUtil.getEvent(event); };
10 事件类型
(1)ui 事件:
-
DOMActivate: 表示元素已经被用户操作激活
- load:当页面完全加载后在 window 上面触
- unload:当页面完全卸载后在 window 上面触发
- abort:在用户停止下载过程时,如果嵌入的内容没有加载完,则在<object>元素上面触发
- error:当发生 JavaScript 错误时在 window 上面触发
- select:当用户选择文本框(<input>或<texterea>)中的一或多个字符时触发
- resize:当窗口或框架的大小变化时在 window 或框架上面触发
- scroll:当用户滚动带滚动条的元素中的内容时,在该元素上面触发。
(2)焦点事件
- blur: 在元素失去焦点时触发。这个事件不会冒泡;所有浏览器都支持
- focus: 在元素获得焦点时触发。这个事件不会冒泡;所有浏览器都支持
- focusin:在元素获得焦点时触发。会冒泡
- focusout:在元素失去焦点时触发
其中,blur、和focusout的事件目标是失去焦点的元素;而focus、 focusin 的事件目标是获得焦点的元素。
(3)鼠标与滚轮事件
- click:在用户单击主鼠标按钮(左边按钮)或者按下回车键时触发,这一点对确保 易访问性很重要,意味着 onclick 事件处理程序既可以通过键盘也可以通过鼠标执行。
- dblclick:在用户双击主鼠标按钮(左边按钮)时触发
- mousedown:在用户按下了任意鼠标按钮时触发。不能通过键盘触发这个事件。
- mouseenter:在鼠标光标从元素外部首次移动到元素范围之内时触发。这个事件不冒泡,而且 在光标移动到后代元素上不会触发。
- mouseleave:在位于元素上方的鼠标光标移动到元素范围之外时触发。这个事件不冒泡,而且在光标移动到后代元素上不会触发。
- mousemove:当鼠标指针在元素内部移动时重复地触发。不能通过键盘触发这个事件。
- mouseout:当鼠标移出目标元素上方触发,不能通过键盘触发这个事件。
- mouseover: 鼠标移入目标元素上方,鼠标移到其后代元素上时会触发,不能通过键盘触发这个事件。
- mouseup: 在用户释放鼠标按钮时触发,不能通过键盘触发这个事件。
双击事件触发顺序:
(1) mousedown (2) mouseup (3) click (4) mousedown (5) mouseup (6) click (7) dblclick
ie下:
IE8 及之前版本中的实现有一个小 bug,因此在双击事件中,会跳过第二个 mousedown 和 click事件,其顺序如下:
(1) mousedown(2) mouseup(3) click 9 (4) mouseup(5) dblclick
IE9 修复了这个 bug,之后顺序就正确了。
(4)鼠标滚轮事件
IE 6.0 首先实现了 mousewheel 事件。此后,Opera、Chrome 和 Safari 也都实现了这个事件。当用 户通过鼠标滚轮与页面交互、在垂直方向上滚动页面时(无论向上还是向下),就会触发 mousewheel 事件。这个事件可以在任何元素上面触发,最终会冒泡到 document(IE8)或 window(IE9、Opera、 Chrome 及 Safari)对象。与 mousewheel 事件对应的 event 对象除包含鼠标事件的所有标准信息外, 还包含一个特殊的 wheelDelta 属性。当用户向前滚动鼠标滚轮时,wheelDelta 是 120 的倍数;当用 户向后滚动鼠标滚轮时,wheelDelta 是120 的倍数
EventUtil.addHandler(document, "mousewheel", function(event){
event = EventUtil.getEvent(event);
alert(event.wheelDelta); });
Firefox 支持一个名为 DOMMouseScroll 的类似事件,也是在鼠标滚轮滚动时触发。与 mousewheel 事件一样,DOMMouseScroll 也被视为鼠标事件,因而包含与鼠标事件有关的所有属性。而有关鼠标滚 轮的信息则保存在 detail 属性中,当向前滚动鼠标滚轮时,这个属性的值是-3 的倍数,当向后滚动 鼠标滚轮时,这个属性的值是 3 的倍数。
EventUtil.addHandler(window, "DOMMouseScroll", function(event){
event = EventUtil.getEvent(event); alert(event.detail); });
(5)触摸设备
ios 和 android 设备的实现非常特别,因为这些设备没有鼠标。在面向 iPhone 和 iPod 中的 Safari 开发时,要记住以下几点。
- 不支持 dblclick 事件。双击浏览器窗口会放大画面,而且没有办法改变该行为。
- 轻击可单击元素会触发 mousemove 事件。如果此操作会导致内容变化,将不再有其他事件发生;如果屏幕没有因此变化,那么会依次发生 mousedown、mouseup 和 click 事件。轻击不可单 击的元素不会触发任何事件。可单击的元素是指那些单击可产生默认操作的元素(如链接),或 者那些已经被指定了 onclick 事件处理程序的元素。
- mousemove 事件也会触发 mouseover 和 mouseout 事件。
- 两个手指放在屏幕上且页面随手指移动而滚动时会触发 mousewheel 和 scroll 事件。
(6)键盘与文本事件
- keydown:当用户按下键盘上的任意键时触发,而且如果按住不放的话,会重复触发此事件。
- keypress: 当用户按下键盘上的字符键时触发,而且如果按住不放的话,会重复触发此事件。按下 Esc 键也会触发这个事件
- keyup:当用户释放键盘上的键时触发。
- textInput:这个事件是对 keypress 的补充,用意是在将文本显示给用户之 前更容易拦截文本。在文本插入文本框之前会触发 textInput 事件。
在发生 keydown 和 keyup 事件时,event 对象的 keyCode 属性中会包含一个代码,与键盘上一 个特定的键对应。
var textbox = document.getElementById("myText"); EventUtil.addHandler(textbox, "keyup", function(event){ event = EventUtil.getEvent(event); alert(event.keyCode); });
(7)HTML5 事件
- contextmenu:右击菜单事件,可使用该事件自定义菜单
- beforeunload:这个事件会在浏览器卸载页面之前触发,可以通过它来取消卸载并继续使用原有页面
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;
});
为了显示弹出对话框,必须将 event.returnValue 的值设置为要显示给用户的字符串,同时作为函数的值返回
- DOMContentLoaded:window 的 load 事件会在页面中的一切都加载完毕时触发,但这个过程可能会因为要 加载的外部资源过多而颇费周折。而 DOMContentLoaded 事件则在形成完整的 DOM 树之后就会触发, 不理会图像、JavaScript 文件、CSS 文件或其他资源是否已经下载完毕。与 load 事件不同, DOMContentLoaded 支持在页面下载的早期添加事件处理程序,这也就意味着用户能够尽早地与页面 进行交互。
- hashchange :HTML5 新增了 hashchange 事件,以便在 URL 的参数列表(及 URL 中“#”号后面的所有字符串) 发生变化时通知开发人员。
(9)触摸事件
-
touchstart:当手指触摸屏幕时触发;即使已经有一个手指放在了屏幕上也会触发。
- touchmove:当手指在屏幕上滑动时连续地触发。在这个事件发生期间,调用 preventDefault() 可以阻止滚动。
- touchend:当手指从屏幕上移开时触发。
- touchcancel:当系统停止跟踪触摸时触发。
除了常见的 DOM 属性外,触摸事件还包含下列三个用于跟踪触摸的属性。
touches:表示当前跟踪的触摸操作的 Touch 对象的数组。
targetTouchs:特定于事件目标的 Touch 对象的数组。
changeTouches:表示自上次触摸以来发生了什么改变的 Touch 对象的数组。
(10)手势事件
- gesturestart:当一个手指已经按在屏幕上而另一个手指又触摸屏幕时触发。
- gesturechange:当触摸屏幕的任何一个手指的位置发生变化时触发。
- gestureend:当任何一个手指从屏幕上面移开时触发。
只有两个手指都触摸到事件的接收容器时才会触发这些事件。在一个元素上设置事件处理程序,意 味着两个手指必须同时位于该元素的范围之内,才能触发手势事件(这个元素就是目标)。由于这些事 件冒泡,所以将事件处理程序放在文档上也可以处理所有手势事件。此时,事件的目标就是两个手指都 位于其范围内的那个元素。
11. 事件委托
对“事件处理程序过多”问题的解决方案就是事件委托。事件委托利用了事件冒泡,只指定一个事 件处理程序,就可以管理某一类型的所有事件。例如,click 事件会一直冒泡到 document 层次。也就 是说,我们可以为整个页面指定一个 onclick 事件处理程序,而不必给每个可单击的元素分别添加事 件处理程序。
以上是关于js 事件的主要内容,如果未能解决你的问题,请参考以下文章
js 温故而知新 webkitTransitionEnd 监听Transition动画结束事件
谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js
Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段