js是一门事件驱动的编程语言,事件一般有多种,好比说网络事件,IO事件,定时事件,点击事件等等。 在这里先只关注下前端浏览器中的事件。前端
如同字面意思,事件就表明了一件事或一个动做,浏览器中的事件有哪些node
window事件 | form事件 | keyboard事件 | mouse事件 | media事件 |
---|---|---|---|---|
afterprint | onblur | onkeydown | onclick | onabort |
beforeprint | onchange | onkeypress | ondbclick | oncanplay |
onload | oncontextmenu | onkeyup | ondrag | oncanplaythrough |
onunload | onformchange | ongragend | ondurationchange | |
onbeforeunload | onforminput | ondragenter | onemptied | |
onerror | onforcus | ondragleave | onended | |
onhaschange | oninput | ondragover | onerror | |
onmessage | oninvalid | ondragstart | onloadeddata | |
onoffline | onreset | ondrop | onloadedmetadata | |
ononline | onselect | onmousedown | onloadstart | |
onpagehide | onsubmit | onmousemove | onpause | |
onpageshow | onmouseout | onplay | ||
onpopstate | onmouseover | onplaying | ||
onredo | onmouseover | onprogress | ||
onresize | onmoseup | onratechange | ||
onstorage | onmosewhell | onreadystatechange | ||
onundo | onscroll | onseeked | ||
onunload | onseeking | |||
onstalled | ||||
onsuspend | ||||
ontimeupdate | ||||
onvolumechange | ||||
onwaiting |
从上面各方各面的事件上咱们能够看出浏览器冲加载到退出那一刻,无时不刻不在触发事件,那么事件触发是怎样的一个流程呢?编程
当dom节点发生了某些操做时,就会有一个事件发射出去,这个事件从window发出,不断通过下级节点知道目标节点,这个阶段称为捕获阶段。全部通过的节点都会触发这个事件,捕获阶段的任务就是创建事件传递线路,以便后面冒泡阶段顺着该线路返回至window。监听该阶段的事件,能够经过把addEventListener第三个参数设为true浏览器
node.addEventListener('click', function() {}, true);
当事件传递到目标节点哪里,最终会在目标节点上触发这个事件,这个就是目标阶段(事件触发的目标老是最最底层的节点:如<p>hello <em>world</em></p>,目标节点能够是p也能够是em)网络
当事件到达目标节点以后,会沿捕获阶段的路线原路返回,这个阶段称为冒泡阶段,一样沿途全部的节点都会再次触发该事件。dom
由事件的触发机制咱们能够看到,沿途全部的父节点都会被触发两次该事件,一次是捕获阶段,一次是冒泡阶段。编程语言
node.addEventListener('click', functioon() {console.log('hello')}, true) ; //捕获阶段 node.addEventListener('click', function() {console.log('world')}, false); //冒泡阶段
因此咱们能够经过冒泡机制来监听父节点的事件,实现监听子节点,尤为是当子节点很是多的时候ide
注:因为IE浏览器不支持在捕获阶段监听事件,全部一般只用冒泡阶段来监听事件。函数
事件的冒泡机制,虽然很好,但有些场合并不使用。在比较复杂的应用中,监听比较复杂,咱们可能只但愿监听发生具体事件的节点,这个时候就要阻止冒泡spa
阻止冒泡可使用事件对象的stopPropagation方法
node.addEventListener('click', function(e) { //operations e.stopPropagation(); }, false);
在阻止冒泡时咱们使用到了事件对象,那么事件对象是什么? 当一个事件被触发的时候,会建立一个事件对象,这里面包含了一些有用的属性和方法,事件对象会做为回调函数的的第一个参数(如同node回调第一个参数永远是error同样)
<body> <div class="one"> <div class="two"> <div class="three"> </div> </div> </div> </body> node.addEventListener('click', function(e) { console.log('事件对象', e) }, false);
事件对象的属性和方法等(方法大部分上是对属性的get方法)
属性 | 描述 | 方法 | 描述 |
---|---|---|---|
altKey | addEventListener | 添加事件绑定 | |
bubbles | 是否在冒泡阶段触发 | removeEventListener | 删除事件绑定 |
button | stopPropagation | 中止冒泡 | |
buttons | preventDefault | 禁止浏览器默认行为 | |
cancelBubble | dispatchEvent | 手动触发事件(var event=new Event('click'); element.dispatchEvent(event) ) |
|
cancelable | 是否能够调用proventDefault来禁止 | ||
clientX | |||
clientY | |||
composed | |||
ctrlKey | |||
currentTarget | |||
defaultPrevented | 是否禁止了默认行为 | ||
detail | |||
eventPhase | 当前事件触发在什么阶段。none:0;捕获:1;目标:2;冒泡:3 | ||
fromElement | |||
isTrusted | 浏览器触发(用户真实操做触发),仍是 JavaScript 代码触发的 | ||
layerX | |||
layerY | |||
metaKey | |||
movementX | |||
movementY | |||
offsetX | |||
offsetY | |||
pageX | 页面的坐标 | ||
pageY | 页面的坐标 | ||
path | 事件路径 | ||
relatedTarget | |||
returnValue | |||
screenX | |||
screenY | |||
shiftKey | |||
sourceCapabilities | |||
srcElement | ie6-8 的触发事件的 dom 元素,非标准 | ||
target | 触发的目标节点 | ||
timeStamp | 返回事件发生时的时间戳 | ||
toElement | |||
type | 事件类型 | ||
view | |||
which | |||
x | |||
y |
传统的事件绑定存在两个不足的地方:1)须要绑定不少个eventhandler 2)事件没法绑定后加入的节点。 事件的代理或委托就是事件触发过程当中冒泡机制和事件对象的应用,j简单的结构以下
document.getElementById("parent-list").addEventListener("click",function(e) { // e.target是被点击的元素! // 若是被点击的是li元素 if(e.target && e.target.nodeName == "li") { // 找到目标,输出ID! console.log("find"); } });