事件
事件
光有 DOM 是无法进行交互的,还得有“事件”。事件,就是文档或浏览器窗口中发生的一些特定交互瞬间,JS 与 HTML 之间的交互正是通过事件实现的。事件的概念起源于 IE3 和 Navigator 2 ,当时的事件只是作为分担服务器运算负载的一种工具。说到事件不得不提起的一个概念就是事件流,事件流描述的是从页面中接收事件的顺序,然而,该死的有两种截然相反的事件流,一个是 IE 事件流(事件冒泡流),另一个是 Netscape 事件流(事件捕获流)。IE 事件流也称为事件冒泡,事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐层向上传播直到 document (有些版本的浏览器还会冒泡到 window) 。事件捕获则完全相反,最具体的节点在最后才能捕获到事件,它的用意在于在事件到达预定目标之前捕获它。然而,DOM 2 对事件流做了一个规定:事件流包括3个阶段,事件捕获阶段、目标阶段和事件冒泡阶段。首先发生的是事件捕获,为截获事件提供了机会;然后是目标阶段,目标节点接收到事件;最后一个是冒泡阶段,可以在此阶段对事件作出响应。
介绍完两个基本概念到主角上场了 —— 事件处理程序。听上去貌似挺高大上,通俗的说,事件就是用户或浏览器自身执行的某些动作,比如说鼠标点击,滑动等。而事件处理程序就是响应某个事件的函数(也称为事件侦听器)。事件处理程序分为以下几种:
① HTML 事件处理程序
通过 HTML 的特性来实现的,举个直白的例子就是直接在 HTML 标签上绑定监听,这种方式的耦合度太高了,也很少会使用,所以就忽略吧~~
② DOM 0 事件处理程序
将一个函数赋值给一个事件处理程序属性,事件处理程序属性也就是以 ‘on’开头的那些事件名,比如 onclick 等等。
var btn = document.getElementById("myBtn") btn.onclick = function(){ alert(this.id) }
这里需要注意的是方法里面的 this 指向的是对应的 DOM 元素。
③ DOM 2 事件处理程序
DOM 2 定义了两个方法,用于处理指定和删除事件处理程序的操作: addEventListener( ) 和 removeEventListener( ) 。所有 DOM 节点中都包含这两个方法,并且它们都接受 3 个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是 true ,表示在捕获阶段调用事件处理程序;如果是 false ,表示在冒泡阶段调用事件处理程序。
const test = document.getElementById('test') test.addEventListener('click',function () { console.log(this.id) // test })
同样的,方法里面的 this 也是DOM 元素。与 DOM 0 不同的是,这种方式可以绑定多个同类型的事件监听函数,如:
const test = document.getElementById('test') test.onclick = function () { console.log('1') } test.onclick = function () { console.log('2') } test.addEventListener('click',function () { console.log('3') }) test.addEventListener('click',function () { console.log('4') })
输出的结果是:2 3 4 ,而 1 没有被输出是因为被后面的方法覆盖了。
④ IE 事件处理程序
IE 实现了与 DOM 2 中类似的两个方法: attachEvent() 和 detachEvent() 。这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。由于 IE8 及更早版本只支持事件冒泡,所以通过attachEvent() 添加的事件处理程序都会被添加到冒泡阶段。
var btn = document.getElementById("myBtn"); btn.attachEvent("onclick", function(){ alert("Clicked"); })
需要注意的是,方法里面的 this 指向的是 window ,所以也可以通过这点来实现跨浏览器版本的特殊需求。
其实这些监听函数都有一个默认参数 event ,也就是事件对象。在触发 DOM 上的某个事件时,会产生一个事件对象 event ,这个对象中包含着所有与事件有关的信息。比如常见的 event.type 就是指被触发的事件类型,event.target 就是指事件的目标。IE 中的事件对象则是 window上的一个属性,window.event 。