事件模型是JS里十分重要的一个部分,这两天查询了一些相关资料,用自己的文字记录一下。本文不讨论IE。
事件模型
DOM事件模型
最简单且兼容所有浏览器的事件模型,有两种方式。默认发生在冒泡阶段。
HTML中直接绑定(不推荐)
<button id="button" onclick="click()">ClickMe</button>
JS指定属性值
var button = document.getElementById("button")
button.onclick = function() {
//...
}
DOM 2级模型
属于W3C标准模型,先事件捕获,到达目标后再进行冒泡。兼容现代浏览器。
//DOM 2级事件第三个参数是一个布尔值(默认为false),true表示捕获阶段调用事件处理程序,false表示冒泡阶段调用事件处理程序。
var button = document.getElementById("button")
button.addEventListener('click', function() {
//...
}, false)
事件对象
触发DOM上的事件后,会产生一个事件对象event,作为参数传给监听函数。所有的事件都是这个事件对象的示例。
事件对象常用属性
type 被触发的事件的类型
target 事件的目标
currentTarget 注册这个事件监听的对象
事件对象常用方法
preventDefault() 取消事件的默认行为
stopPropagation() 阻止事件继续传播(冒泡和捕获),不包括在当前节点上其他的事件监听函数。
stopImmediatePropagation() 阻止所有事件继续传播,包括在当前节点上其他的事件监听函数。
<body>
<div id="pop-up-window"></div>
</body>
<script>
var body = document.querySelector('body')
var popUpWindow = document.getElementById('pop-up-window')
body.addEventListener('click', function(e) {
popUpWindow.style.display = 'none'
}, false)
popUpWindow.addEventListener('click', function(e) {
e.stopPropagation() //在弹窗内部点击时阻止事件传播,因此不会触发body的click事件
}, false)
</script>
事件委托
借助事件冒泡和事件对象,可以实现事件委托(又叫事件代理)。
先思考如何给下面的按钮都绑定一个click事件,点击后输出按钮的id
<div id="contiainer">
<button id="button1">button1</button>
<button id="button2">button2</button>
<button id="button3">button3</button>
<!-- ... -->
<button id="button10">button10</button>
</div>
或许你或你以前会这么写
for (var i = 1; i <= 10; i++) {
document.getElementById("button" + i).addEventListener('click', function(e) {
console.log(e.target.id)
}, false)
}
每个函数都是对象,都会占用内存,现在创建了10个监听事件,影响了页面性能。我们利用事件委托(又叫事件代理)可以解决这个问题。事件委托借助事件冒泡和事件对象,只需要创建一个监听器,就可以管理一个类型的所有事件。只需要在DOM树尽量最高的层次创建一个监听。
document.getElementById('container').addEventListener('click', function(e) {
if (e.target.tagName.toLowerCase() === 'button') console.log(e.target.id)
}, false)