1 事件流
事件流分为三阶段。
第一阶段为捕获阶段(capture phase) 该阶段包括从窗口到目标节点的父节点范围内的所有节点,图片中红线指示。
第二部分称为目标阶段(target phase) 该阶段仅包括目标节点。
第三部分称为冒泡阶段(bubble phase) 冒泡阶段包括从目标节点的父节点返回到窗口的行程中遇到的节点。
addEventListener(eventType,fn, {capture:false}) 给节点 注册监听事件。(IE8用attachEvent('on'+eventType ,fn)
举例来看
document
html
body
button#btn
var btn = document.querySelector('#btn');
btn.addEventListner('click' ,function(e){ alert('btn') });
document.body.addEventListner('click' ,function(e){ alert('body')});
addEventListener默认useCapture是false;我们给按钮btn 和 body分别添加了响应 点击click行为的 监听事件。
当我们点击按钮会 先后 弹出 ‘btn’ 和 ‘body’
执行流程是先捕获阶段,从窗口一直到btn的parentNode也就是body都没有注册用于捕获阶段的事件。之后到目标阶段弹出‘btn’,然后到冒泡阶段 冒到body 弹出‘click’。
我们将body上用于冒泡阶段的事件变更为 捕获capture 阶段看看是什么效果
var btn = document.querySelector('#btn');
btn.addEventListner('click' ,function(e){ alert('btn') });
document.body.addEventListner('click' ,function(e){ alert('body')}, {capture:true});
这时候body节点上就没有冒泡阶段的 注册事件了。`
执行结果 先后 弹出 'body' 和 'btn'
2 事件的传播
事件在任意阶段 都可以阻止事件继续流动
Event对象提供stopPropagation() 以及stopImmediatePropagation()来阻止事件传播
假设在节点上注册多个同一类型的监听事件
var btn = document.querySelector('#btn');
btn.addEventListner('click' ,function(e){ alert('btn1') }//fn1);
btn.addEventListner('click' ,function(e){ alert('btn2') }//fn2);
document.body.addEventListner('click' ,function(e){ alert('body')} ,true);
//数据结构如下dom#btn — key : click, value : [fn1 ,fn2]
当我们在f1中 加上
btn.addEventListner('click' ,function(e){ alert('btn1');e.stopImmediatePropagation() }//fn1);
点击按钮后弹出btn1 ,btn2 。(执行了fn1,fn2)并不会弹出 body 因为在目标阶段阻止了事件继续传, 在fn2中添加同样有此效果。
但当我们在f1中 加上 e.stopPropagation() 同类型的事件也不会继续执行 。
数据结构 key : click, value : [fn1 ,fn2] ,只会执行fn1
3 事件的默认行为
有些事件会有默认行为, 比如鼠标在图片上按下(mousedown)能拖动图片 ,submit按钮点击(click)能发送http请求
event.preventDefault() 可以取消这种默认行为。(IE8 event.returnValue = false )
4 事件的定义以及触发
在非IE浏览器中 我们定义事件可以是这样
Event(type,[options])
var event= new Event('event' ,{bubbles:true});
var customEvent= new CustomEvent('customEvent' ,{detail:{data:'test' } ,bubbles:true});
CustomEvent自定义事件 ,可以使用detail携带数据,而Event不可以。bubbles可以决定该事件是否允许冒泡
触发事件dispatcherEvent
target.dispatcherEvent(evt) evt事件会从document.defaultView(window)传播到目标,再冒泡至窗口.
IE8 var event= document.createEvent('HTMLEvents'); UIEvents|MouseEvents...
event.initEvent(type, bubbles, cancelable);
移除事件 removeEventListener(type, callback, options) , 移除事件条件非常苛刻,所以通常进行对addEventListener进行warp,让返回callback,用于remove IE8(detachEvent)
`