Open
Description
一、浏览器事件
1.1 事件传播
- 整个过程中事件对象是同一个,即所有的事件处理函数操作的是同一个对象;
- 所有的事件都会有捕获阶段,但是并不是所有的事件都会经历冒泡阶段(比如
focus
事件);
各阶段Event.currentTarget
, Event.target
,Event.eventPhase
的取值
Event.eventPhase
表示事件对象所处的阶段;- 传播过程中
Event.target
取值始终不变,即使事件处理完毕后; - 传播过程中
Event.currentTarget
取值表示当前绑定事件处理函数的EventTarget
对象,所以会变;并且事件处理完毕后Event.currentTarget
都会变成null
。
当心异步访问Event.currentTarget
。
阻止传播
Event.cancelBubble=true
/Event.stopPropagation
/Event.stopImmediatePropagation
阻止传播,在各阶段调用都有效;Event.cancelBubble=true
和Event.stopPropagation`是等价的。
1.2 绑定事件的方式
3中方式
- html特性
- DOM的
onXXX
属性 addEventListener
IE兼容attachEvent
1.2 触发事件
除了用户触发事件外,还可以通过JS直接触发事件。但是两种方式存在差异。
JS触发
- JS里触发事件(
dispatchEvent
,HTMLElement.click
,HTMLElement.focus
)是同步的; - 事件处理函数都是同步调用的;
- 整个冒泡和捕获流程中都是同步执行的。
<button id="btn">click</button>
<script>
var oBtn = document.getElementById('btn')
oBtn.addEventListener('click', function () {
Promise.resolve().then(() => console.log('微任务 1'))
console.log('listener1')
})
oBtn.addEventListener('click', function () {
Promise.resolve().then(() => console.log('微任务 2'))
console.log('listener2')
})
oBtn.click()
console.log('after click')
</script>
看下这个问题点击鼠标和主动调用click方法有什么不同,为什么有下面这种现象。
用户触发
用户触发的事件是由浏览器通过eventQueue告诉程序的。并且整个捕获冒泡过程中所有的事件处理函数都是异步调用。
demo
既然都是异步的,那怎么之前事件被取消了?
1.3 执行事件处理函数
- 不同的触发事件方式(如上)导致的事件处理函数调用方式不同;
- 实参是事件对象;
3this
是当前绑定事件处理函数的EventTarget
,注意不一定是触发事件的EventTarget
。
1.4 事件代理
如下
二、APIs
事件相关的APIs主要是:
- EventTarget
可以添加、触发,接收事件的对象。 - Event对象
事件处理函数接收的实参,即事件对象。 - EventListener
可以处理事件的对象。这个很少用到,一般直接给EventTarget.addEventListener
直接指定callback
。
2.1 EventTarget
3大功能:
- 添加事件处理函数;
- 删除事件处理函数;
- 触发事件。
在设计模式里叫什么?
addEventListener
- option参数;
- Passive Event ;
- 回调函数的
this
是绑定事件处理函数的EventTarget
对象。
不一定是触发事件的EventTarget
对象。
removeEventListener
dispatchEvent
- 可以通过在创建事件对象时指定的
bubbles
的值控制触发的事件是否走事件捕获和冒泡阶段; - 事件处理函数可以利用
Event.isTrusted
属性判断事件是由用户触发的还是JS触发的。 -
Unlike "native" events, which are fired by the DOM and invoke event handlers asynchronously via the event loop, dispatchEvent() invokes event handlers synchronously
2.2 Event对象
preventDefault()
/defaultPrevented
/cancelable
stopPropagation()
/cancelBubble
stopImmediatePropagation()
eventPhase
target
/currentTarget