浏览器事件链
绑定事件
1 | //options: |
1 | //内部结构: |
触发事件
从target_element上开始触发事件
事件类型
- Event:CAPTURING_PHASE (捕获事件,从父元素到子元素)
- Event:AT_TARGET (命中事件,触发元素)
- Event:BUBBLING_PHASE (冒泡事件,从子元素到父元素)
事件链EventPath
EventPath = [targetElement, …, HTMLBodyElement, HTMLHtmlElement, HTMLDocument, HTMLDocument]
第2个HTMLDocument的currentTarget为DomWindow
事件执行过程
- CAPTURING_PHASE:path=[EventPath.last,…,EventPath.first+1] ==>currentTarget->fireEventListeners
- AT_TARGET:path=[EventPath.first] ==>currentTarget->fireEventListeners
- BUBBLING_PHASE:path=[EventPath.first+1,…,EventPath.last] ==> currentTarget->fireEventListeners
问题
当一个Element上同时绑定capture和bubbling事件时,如何触发?
- 非At_TARGET的Element,按照正常执行顺序,先执行capture路径,再target,再bubbling路径
- 在At_TARGET 的Element, 只按照绑定时候的顺序执行,不区分capture和bubbling
原因:1
2
3
4
5
6
7
8//fireEventListeners时
//CAPTURING_PHASE和BUBBLING_PHASE过程时,如果eventPhase和useCapture不匹配,
//会被拦截后 continue,
//但是在At_TARGET的过程没有这层拦截
if (event.eventPhase() == Event::CAPTURING_PHASE && !registeredListener->useCapture())
continue;
if (event.eventPhase() == Event::BUBBLING_PHASE && registeredListener->useCapture())
continue;