事件:系统内发生的动作或事情,会产生或触发某种信号,所有的 DOM 节点都生成这样的信号
事件处理程序:响应事件的的一个处理程序,在事件发生时运行的函数
事件处理程序设置方法
1. HTML 特性
在标签中添加 on<event>
attribute(不区分大小写):
2. DOM 属性
在 JS 里给元素对象的 on<event>
赋值(区分大小写)(只能为同一个事件分配一个处理程序):
移除处理程序:elem.onclick = null
注意
如果将一个现存的函数赋值给处理程序,在 JS 里不加括号,在标签上要加括号
因为在 JS 里加括号则表示调用,会把函数返回值赋值进去,
而当浏览器读取 HTML attribute 时,会使用 赋值的内容 创建一个处理程序,自动包一层 function
3. addEventListener 方法
可以为同一个事件分配多个处理程序,同一个事件的运行顺序和创建顺序相同:element.addEventListener (event, handler[, options])
event
:事件名,如:“click”handler
:处理程序options
:具有以下属性的附加可选对象:- once:如果为 true,那么会在被触发后自动删除监听器
- capture:事件处理的阶段,由于历史原因,options 也可以是 false/true,它与 {capture: false/true} 相同
- passive:如果为 true,表示约定处理程序将不会调用 preventDefault(),如果里面还是调用了,会抛出警告(用于性能优化)
- signal:该 AbortSignal 的 abort() 方法被调用时,监听器会被移除
移除处理程序:element.removeEventListener (event, handler[, options])
注意传入的 event,handler 和 capture 要一样才能移除。如:事件处理函数要用引用传入,保证与创建时一样才能移除,而且要同一冒泡/捕获阶段
Tip
handler 除了是函数外,还可以是一个对象。只要这个对象里有 handleEvent 方法,当事件发生时就会调用这个方法
NOTE
- 有些事件无法通过 DOM 属性进行分配,只能使用 addEventListener,所以 addEventListener 更通用
- 无论 addEventListener 怎样,
on<event>
处理程序都会触发
event
当事件发生时,浏览器会创建一个 event 对象,将详细信息放入其中,并将其作为参数传递给处理程序
type
:事件类型event.target
:触发事件的元素,不会发生变化event.currentTarget
:处理事件的元素,会在冒泡/捕获时发生变化event.eventPhase
:当前处于哪个 事件阶段event.defaultPrevented
:用于确定事件的默认行为是否已被取消(调用过event.preventDefault()
方法)
this
处理程序中的 this 的值是当前的元素,也就是处理程序所在的那个元素 (this === event.currentTarget
)
事件阶段
事件传播有三个阶段:
- 捕获阶段(
CAPTURING_PHASE
:1):事件从 window 向下传入目标元素 - 目标阶段(
AT_TARGET
:2):事件到达目标元素 - 冒泡阶段(
BUBBLING_PHASE
:3):事件从目标元素向上传到 window
捕获
很少使用,上面添加事件处理程序的几种方式都默认只是在 目标阶段 和 冒泡阶段
如果要在捕获阶段触发,则设置 addEventListener 的 capture 为 true
冒泡
当一个事件发生在一个元素上,它会首先运行在该元素上的处理程序,然后运行其父元素上的处理程序,然后一直向上到其他祖先上的处理程序
事件委托
如果有多个元素需要相同的处理程序,那么可以不用每个元素都写一个处理程序,而是在它们的共同祖先元素上绑定事件,然后在处理程序里判断 event.target
进行不同的处理
优点:
- 节省内存
- 更少的代码
- 可以方便地进行内层的 DOM 修改
缺点:
- 事件必须冒泡,而有些事件不会冒泡或阻止了冒泡
- 可能会增加 CPU 负载,因为容器级别的处理程序会对容器中任意位置的事件做出反应,但是一般忽略不计
停止传播(停止冒泡和停止捕获)
event.stopPropagation()
:停止当前事件继续传播stopImmediatePropagation()
:停止元素上所有事件的继续传播
通常,没有真正必要去阻止传播。一项看似需要阻止传播的任务,可以通过其他方法解决,其中之一就是使用自定义事件
浏览器默认行为
很多事件会自动触发浏览器执行某些行为:
mousedown
:在文本上按下鼠标按钮并移动:选中文本- 在
<input type="checkbox">
上click
:选中/取消选中 input - 点击
<input type="submit">
或者在表单字段中按下 Enter 键:浏览器将提交表单,触发提交到服务器的行为 - 点击链接自动跳转到对应 url
- 鼠标右键单击时,显示浏览器上下文菜单
阻止浏览器默认行为:
- 主流做法:
event.preventDefault()
- 如果处理程序是使用
on<event>
(而不是 addEventListener)分配的,需要返回 false(其他情况下处理程序的返回值没有任何意义)
注意 on<event>
要接受到 false:
Tip
有些事件会自动触发另一个事件,如果阻止了会一并阻止