JavaScript HTML DOM EventListene
监听事件
浏览器会根据某些操作触发对应事件,如果我们需要针对某种事件进行处理,则需要监听这个事件。监听事件的方法主要有以下几种:
- HTML 内联属性(避免使用)
<button onclick="alert('你点击了这个按钮');">点击这个按钮</button>
onclick
属性表示触发 click
,属性值的内容(JavaScript 代码)会在单击该 HTML 节点时执行.
这种方法,JavaScript 代码与 HTML 代码耦合在了一起,不便于维护和开发
- DOM 属性绑定
element.onclick = function(event){
alert('你点击了这个按钮');
};
上面代码就是监听 element
节点的 click
事件.
简单易懂,而且有较好的兼容性
但因为直接赋值给对应属性,如果你在后面代码中再次为 element 绑定一个回调函数,会覆盖掉之前回调函数的内容.
- 使用事件监听函数
语法:
element.addEventListener(<event-name>, <callback>, <use-capture>);
在 element 这个对象上面添加一个事件监听器,当监听到有 <event-name> 事件发生的时候,调用 <callback> 这个回调函数。至于 <use-capture> 这个参数,表示该事件监听是在“捕获”阶段中监听(设置为 true)还是在“冒泡”阶段中监听(设置为 false), 默认值为false.
var btn = document.getElementsByTagName('button');
btn[0].addEventListener('click', function() {
alert('你点击了这个按钮');
}, false);
移除事件监听
当我们为某个元素绑定了一个事件,每次触发这个事件的时候,都会执行事件绑定的回调函数。如果我们想解除绑定,需要使用 removeEventListener 方法:
element.removeEventListener(<event-name>, <callback>, <use-capture>);
需要注意的是,绑定事件时的回调函数不能是匿名函数,必须是一个声明的函数,因为解除事件绑定时需要传递这个回调函数的引用,才可以断开绑定。例如:
<button id="btn">点击这里</button>
<script>
var btn = document.getElementById('btn');
var fun = function(){
alert('这个按钮只支持一次点击');
btn.removeEventListener('click', fun, false);
};
btn.addEventListener('click', fun, false);
</script>
时间触发过程
-
捕获阶段(Capture Phase)
当我们在 DOM 树的某个节点发生了一些操作(例如单击、鼠标移动上去),就会有一个事件发射过去。这个事件从 Window 发出,不断经过下级节点直到目标节点。在到达目标节点之前的过程,就是捕获阶段(Capture Phase)。
监听某个在捕获阶段触发的事件,需要在事件监听函数传递第三个参数 true:
element.addEventListener(<event-name>, <callback>, true);
捕获阶段的任务就是建立这个事件传递路线,以便后面冒泡阶段顺着这条路线返回 Window。
-
目标阶段(Target Phase)
当事件跑到了事件触发目标节点那里,最终在目标节点上触发这个事件,就是目标阶段。
需要注意的时,事件触发的目标总是最底层的节点。比如你点击一段文字,你以为你的事件目标节点在 div 上,但实际上触发在 <p>、<span> 等子节点上。例如:
<div>
<p>这是一段话,这里有个<strong>加粗字体</strong>。</p>
</div>
<script>
document.addEventListener('click', function(e){
alert(e.target.tagName);
}, false);
</script>
以上监听单击事件,将目标节点的 tag name 弹出。当你点击加粗字体时,事件的目标节点就为最底层的 <strong> 节点
-
冒泡阶段(Bubbling Phase)
在实际使用中,并不需要把事件监听函数准确绑定到最底层的节点也可以正常工作。比如在上例,为这个 <div> 绑定单击时的回调函数,无须为这个 <div> 下面的所有子节点全部绑定单击事件,只需要为 <div> 这一个节点绑定即可。因为发生它子节点的单击事件,都会冒泡上去,发生在 <div> 上面
demo
为什么不用第三个参数 true
这是因为 IE 浏览器不支持在捕获阶段监听事件,为了统一而设置的,毕竟 IE 浏览器的份额是不可忽略的。
向同一个元素中添加多个事件句柄
addEventListener() 方法允许向同个元素添加多个事件,且不会覆盖已存在的事件:
<p>该实例使用 addEventListener() 方法向同个按钮中添加两个点击事件。</p>
<button id="myBtn">点我</button>
<script>
var x = document.getElementById("myBtn");
x.addEventListener("click", myFunction);
x.addEventListener("click", someOtherFunction);
function myFunction() {
alert ("Hello World!")
}
function someOtherFunction() {
alert ("函数已执行!")
}
</script>
<p>实例使用 addEventListener() 方法在同一个按钮中添加多个事件。</p>
<button id="myBtn">点我</button>
<p id="demo"></p>
<script>
var x = document.getElementById("myBtn");
x.addEventListener("mouseover", myFunction);
x.addEventListener("click", mySecondFunction);
x.addEventListener("mouseout", myThirdFunction);
function myFunction() {
document.getElementById("demo").innerHTML += "Moused over!<br>"
}
function mySecondFunction() {
document.getElementById("demo").innerHTML += "Clicked!<br>"
}
function myThirdFunction() {
document.getElementById("demo").innerHTML += "Moused out!<br>"
}
</script>
向 Window 对象添加事件句柄
addEventListener() 方法允许你在 HTML DOM 对象添加事件监听, HTML DOM 对象如: HTML 元素, HTML 文档, window 对象。或者其他支出的事件对象如: xmlHttpRequest 对象
<p>实例在 window 对象中使用 addEventListener() 方法。</p>
<p>尝试重置浏览器的窗口触发 "resize" 事件句柄。</p>
<p id="demo"></p>
<script>
window.addEventListener("resize", function(){
document.getElementById("demo").innerHTML = Math.random();
});
</script>