本章内容:
- 事件流:冒泡,捕获,DOM事件流
- 事件处理程序:HTML(内联),DOM0,DOM2,IE,兼容
- 跨浏览器:添加和移除事件处理程序,获取事件对象,取消默认行为,取消冒泡
- 自定义事件:Event,customEvent
17.1 事件流
HTML 中与 javascript 交互是通过事件驱动来实现的。事件流描述的是页面接收事件的顺序
第四代Web浏览器:IE事件流和Netscape事件流完全相反
IE:事件冒泡流
Netscape:事件捕获流
1 |
|
事件冒泡
从具体元素开始触发,从目标元素逐级向上传播
click事件的发生顺序:<div> -> <body> -> <html> -> document
所有现代浏览器都支持,但是实现方式有区别
- IE5.5即以前会跳过
<html>
,直接<body> -> document
- 现代浏览器会一直冒泡到
window
对象
事件捕获
最不具体的元素最先收到事件,目的是想在目标元素接收到事件之前拦截事件
从document逐级向下传播到目标元素
click事件的发生顺序:document -> <html> -> <body> -> <div>
旧版本浏览器不支持,现实基本不用
DOM事件流
DOM2 Events规范规定,事件流分三个阶段:事件捕获、到达目标、事件冒泡
- 事件捕获:用来提前拦截事件
- 到达目标:目标元素接收事件
- 事件冒泡:最迟在这一阶段响应事件
所有现代浏览器都支持,只有IE8及以前不支持
17.2 事件处理程序
事件处理程序的名字以”on”开头, 例如click事件的处理程序叫作onclick
HTML事件处理程序
HTML中的书写方式
1 | <script> |
HTML元素中的this指针指向事件的目标元素
注意,showMessage函数中的this指向全局变量
DOM0事件处理程序
把一个函数赋值给 (DOM元素的)一个事件处理程序属性
脚本中的书写方式
1 | let btn = document.getElementById("myBtn"); |
函数中的this指针指向事件的目标元素
DOM2事件处理程序
使用addEventListener()和removeEventListener()。
这两个方法暴露在 所有DOM节点上,它们接收3个参数:
- 事件名,注意是事件名!没有on!!!
- 事件处理函数,如果函数在其他地方定义,传函数名不要括号!!!!
- 一个布尔值,
- true表示在捕获阶段调用事件处理程序,
- false(默认值)表示 在冒泡阶段调用事件处理程序。
可以为一个事件添加多个事件处理函数,会按添加顺序执行
1 | function show(){ |
如果addEventListener()添加的是匿名函数,那么removeEventListener()无法删除
事件处理程序一般添加到冒泡阶段,因为这样跨浏览器兼容好,捕获阶段一般用来拦截事件,没有拦截需求就不要置true!
IE事件处理程序
attachEvent()和detachEvent(),只在IE浏览器生效,IE11也不支持
接收两个同样的参数:事件处理程序的名字(有on)和事件处理函数,只会添加到冒泡阶段,因为IE8及以前只支持冒泡
1 | function showThis() { |
使用attachEvent()时,事件处理程序在全局作用域中运行,this指向window
跟DOM2一样也可以添加很多事件处理程序,但是触发顺序相反,是添加顺序的逆序
跟DOM2一样也不能删除匿名函数
跨浏览器事件处理程序
p777
检测浏览器对事件处理程序的支持,并分类实现
1 | var EventUtil = { |
17.3 事件对象
DOM事件对象
event对象,是传给事件处理程序的唯一参数,用DOM0或DOM2指定事件处理程序时,都会传入这个event对象
一些常用属性和方法:
event.type 事件类型
event.target 事件目标(目标元素)
event.preventDefault() 取消事件的默认行为(例如drag)
IE事件对象
IE事件对象根据不同的事件处理程序访问
DOM0:event对象是window对象的一个属性,在事件处理函数里let event=window.event
,然后就可以用event.type之类的
IE:用attachEvent指定事件处理程序,event就是唯一的参数传给事件处理函数,同时它依然是window的属性,只是图方便所以传参了
HTML:直接在HTML里指定事件处理程序,可以通过event访问,因为HTML里event是一个自动生成的局部变量
跨浏览器事件对象
p786
兼容性跨浏览器获取event对象,目标元素之类的
- event对象
- 目标元素
- 取消默认行为
- 取消后续事件
1 | var EventUtil = { |
总结
事件流
冒泡和捕获
事件流是页面接受事件的顺序
事件冒泡流:IE浏览器提出,从目标元素逐级向上传播到document(现代浏览器会到window)
事件捕获流:NetScape提出,从document逐级向下传播到具体元素,目的是在目标元素接收到事件之前拦截事件,很多浏览器不支持所以一般不用
DOM事件流
DOM2 Events规范规定,事件流分三个阶段:事件捕获、到达目标、事件冒泡
- 事件捕获:用来提前拦截事件
- 到达目标:目标元素接收事件
- 事件冒泡:最迟在这一阶段响应事件
所有现代浏览器都支持,只有IE8及以前不支持
事件处理程序
事件 click
事件处理程序 onclick
事件处理函数 handleClick()
DOM0 DOM2 *
事件处理程序有哪几种指定方式:HTML、DOM0、DOM2、IE
- HTML:直接在HTML中绑定,
onclick="fun()"
- 标签内的this指向目标元素,函数内的this指向window
- DOM0:
element.onclick=...
- 函数内的this指向目标元素
- DOM2:
addEventListener()
removeEventListener()
- 函数内的this指向目标元素
- 无on
- IE:
attachEvent()
detachEvent()
- 函数内的this指向window
- 有on
addEventListener()参数
事件名、事件处理函数、布尔值(决定将事件处理函数添加到哪个阶段)
- 事件名,注意是事件名!没有on!!!
- 事件处理函数,如果函数在其他地方定义,传函数名不要括号!!!!
- 一个布尔值,
- true表示在捕获阶段调用事件处理程序,
- false(默认值)表示 在冒泡阶段调用事件处理程序。
可以为一个事件添加多个事件处理函数,会按添加顺序执行
addEventListener()和attachEvent()不同
不同点 | addEventListener() | attachEvent() |
---|---|---|
事件处理程序指定方式 | DOM2 | IE |
传入第一个参数 | 事件名无on | 事件处理程序名有on |
传入第三个参数 | 有 | 无 |
事件流阶段 | 可以指定添加到捕获或冒泡 | 只能添加到冒泡 |
浏览器支持 | 现代浏览器都支持 | 只有IE8及以前支持 |
事件处理函数的this指向 | 目标元素 | window |
绑定多个处理函数时的执行顺序 | 顺序 | 逆序 |
冒泡相关
什么事件不会触发冒泡
https://blog.csdn.net/Piconjo/article/details/104729923
前面加on也可以
UI事件:load unload abort error
焦点事件(Focus):blur focus
鼠标事件(Mouse):mouseenter mouseleave
Html5媒体事件(media):play mute
跨浏览器 *
取消冒泡:
DOM0、DOM2中传给事件处理函数的唯一默认参数是event:调用event.stopPropagation()
,可以取消捕获和冒泡
IE中有点不一样:event.cancelBubble = true
,只能取消冒泡
取消默认行为:
DOM:event.preventDefault()
IE:event.returnValue = false
1 | var EventUtil = { |
自定义事件 *
创建事件:3种方法
- Event()构造函数,不能传数据
- customEvent()构造函数,可以传数据
- document.createEvent(),已废弃
触发事件:dispatchEvent(myEvent)
方法1:Event()构造函数
构造函数传入事件名称,可选配置项
- bubbles:是否冒泡
- cancelable:是否被取消
1 | // Event创建事件 |
方法2:customEvent()构造函数
构造函数传入事件名称,可选配置项
- detail:事件种要被传递的数据
- bubbles:是否冒泡
- cancelable:是否被取消
1 | // CustomEvent创建事件 |