目录
0、DOM 标准
1、事件模型
2、事件处理程序
3、事件类型
4、事件对象
正文
0、DOM 标准
在开始学习 JavaScript 事件模型前,我们首先来了解一下什么是 DOM(Document Object Model)
简单来说,DOM 是 W3C 定义的访问 HTML 和 XML 文档的标准
按照不同的发展阶段,分为不同的级别,分别是 DOM0、DOM1、DOM2、DOM3
DOM0、DOM2、DOM3 都有定义与事件相关的内容,但是 DOM1 没有定义与事件相关的内容
1、事件模型
(1)事件捕获
事件从文档对象上开始,然后往下传递,直到目标对象(从父到子),低版本浏览器不支持事件捕获
<!DOCTYPE html> <html> <head> <title>事件捕获</title> </head> <body> <ul> <li>Apple</li> <li>Banana</li> <li>Cherry</li> </ul> </body> <script> let html = document.documentElement html.addEventListener('click', () => { console.log('html') }, true) let body = document.body body.addEventListener('click', () => { console.log('body') }, true) let uls = document.getElementsByTagName('ul') for (let ul of uls) { ul.addEventListener('click', () => { console.log('ul') }, true) } let lis = document.getElementsByTagName('li') for (let li of lis) { li.addEventListener('click', () => { console.log('li') }, true) } // 点击列表项,打印结果为:html body ul li </script> </html>
(2)事件冒泡
事件从目标对象上开始,然后往上传递,直到文档对象(从子到父),所有的浏览器都支持事件冒泡
<!DOCTYPE html> <html> <head> <title>事件冒泡</title> </head> <body> <ul> <li>Apple</li> <li>Banana</li> <li>Cherry</li> </ul> </body> <script> let html = document.documentElement html.addEventListener('click', () => { console.log('html') }, false) let body = document.body body.addEventListener('click', () => { console.log('body') }, false) let uls = document.getElementsByTagName('ul') for (let ul of uls) { ul.addEventListener('click', () => { console.log('ul') }, false) } let lis = document.getElementsByTagName('li') for (let li of lis) { li.addEventListener('click', () => { console.log('li') }, false) } // 点击列表项,打印结果为:li ul body html </script> </html>
(3)事件流模型
DOM2 定义了事件流模型,这是目前广泛使用的 JavaScript 事件模型,规定事件传递先捕获后冒泡
<!DOCTYPE html> <html> <head> <title>事件流模型</title> </head> <body> <ul> <li>Apple</li> <li>Banana</li> <li>Cherry</li> </ul> </body> <script> let html = document.documentElement html.addEventListener('click', () => { console.log('Chtml') }, true) html.addEventListener('click', () => { console.log('Bhtml') }, false) let body = document.body body.addEventListener('click', () => { console.log('Cbody') }, true) body.addEventListener('click', () => { console.log('Bbody') }, false) let uls = document.getElementsByTagName('ul') for (let ul of uls) { ul.addEventListener('click', () => { console.log('Cul') }, true) } for (let ul of uls) { ul.addEventListener('click', () => { console.log('Bul') }, false) } let lis = document.getElementsByTagName('li') for (let li of lis) { li.addEventListener('click', () => { console.log('Cli') }, true) } for (let li of lis) { li.addEventListener('click', () => { console.log('Bli') }, false) } // 点击列表项,打印结果为:Chtml Cbody Cul Cli Bli Bul Bbody Bhtml </script> </html>
2、事件处理程序
(1)DOM0 事件处理程序
通过事件监听函数指定事件处理程序,事件处理程序在冒泡阶段执行
<button id="submit">提交</button>
<script> var button = document.getElementById('submit') // 对于 DOM0 事件处理函数,this 指向目标对象,这里 this 指向 button var handleEvent = function(e) { console.log(this) } // 添加事件处理函数 button.onclick = handleEvent // 删除事件处理函数 button.onclick = null button.onclick = handleEvent </script>
DOM0 事件处理程序,同一个事件只能绑定一个事件处理函数,后面绑定的处理函数会覆盖前面绑定的处理函数
<button id="submit">提交</button>
<script> var button = document.getElementById('submit') var sayHello = function(e) { console.log('Hello') } var sayGoodbye = function(e) { console.log('Goodbye') } button.onclick = sayHello button.onclick = sayGoodbye // 只会打印 Goodbye </script>
(2)DOM2 事件处理程序
通过 addEventListener()
添加事件处理程序,通过 removeEventListener()
删除事件处理程序
它们都接收三个参数,分别是事件名称、事件处理函数以及一个布尔类型的值,这个布尔值默认为
如果布尔值为 false,则在冒泡阶段执行处理函数,如果布尔值为 true,则在捕获阶段执行处理函数
<button id="submit">提交</button>
<script> var button = document.getElementById('submit') // 对于 DOM2 事件处理函数,this 指向目标对象,这里 this 指向 button var handleEvent = function(e) { console.log(this) } // 添加事件处理函数 button.addEventListener('click', handleEvent) // 删除事件处理函数 button.removeEventListener('click', handleEvent) button.addEventListener('click', handleEvent) </script>
DOM2 事件处理程序,同一个事件可以绑定多个事件处理函数,先绑定先执行
<button id="submit">提交</button>
<script> var button = document.getElementById('submit') var sayHello = function(e) { console.log('Hello') } var sayGoodbye = function(e) { console.log('Goodbye') } button.addEventListener('click', sayHello) button.addEventListener('click', sayGoodbye) // 先打印 Hello,再打印 Goodbye </script>
(3)低版本 IE 事件处理程序(IE9 之前)
通过 attachEvent()
添加事件处理程序,通过 detachEvent()
删除事件处理程序
它们都接收两个参数,分别是事件监听函数名称以及事件处理函数,将在冒泡阶段执行处理函数
<button id="submit">提交</button>
<script> var button = document.getElementById('submit') // 对于低版本 IE 事件处理函数,this 指向全局对象,这里 this 指向 window var handleEvent = function() { console.log(this) } // 添加事件处理函数 button.attachEvent('onclick', handleEvent) // 删除事件处理函数 button.detachEvent('onclick', handleEvent) button.attachEvent('onclick', handleEvent) </script>
低版本 IE 事件处理程序,同一个事件可以绑定多个事件处理函数,先绑定后执行
<button id="submit">提交</button>
<script> var button = document.getElementById('submit') var sayHello = function() { console.log('Hello') } var sayGoodbye = function() { console.log('Goodbye') } button.attachEvent('onclick', sayHello) button.attachEvent('onclick', sayGoodbye) // 先打印 Goodbye,再打印 Hello </script>