HTML特性
<script>
function countRabbits() {
for(let i=1; i<=3; i++) {
alert("Rabbit number " + i);
}
}
</script>
<input type="button" onclick="countRabbits()" value="Count rabbits!">
- HTML 特性名是大小写不敏感的,所以
ONCLICK
和onClick
以及onCLICK
都一样可以运行。但是特性通常是小写的:onclick
在HTML特性中,传给onclick的函数需要括号,浏览器将会使用 特性中的内容 创建一个处理程序。所以,标记(markup)会生成下面这个属性:
button.onclick = function() {
countRabbits(); // <-- 特性(attribute)中的内容变到了这里
};
DOM属性
<input id="elem" type="button" value="Click me">
<script>
elem.onclick = function() {
alert('Thank you');
};
</script>
DOM属性区分大小写
- 要移除一个处理程序 —— 赋值
elem.onclick = null
- DOM属性只能绑定一个处理程序
addEventListener
可以为一个事件分配多个处理程序element.addEventListener(event, handler[, options]);
removeEventListener
用于移除处理程序,但必须移除相同的处理程序 ```javascript function handler() { alert( ‘Thanks!’ ); }
input.addEventListener(“click”, handler); // …. input.removeEventListener(“click”, handler);
<a name="C6k5u"></a>
### 事件对象
当事件发生时,浏览器会创建一个 **`event` 对象**,将详细信息放入其中,并将其作为参数传递给处理程序。
```javascript
<input type="button" value="Click me" id="elem">
<script>
elem.onclick = function(event) {
// 显示事件类型、元素和点击的坐标
alert(event.type + " at " + event.currentTarget);
alert("Coordinates: " + event.clientX + ":" + event.clientY);
};
</script>
冒泡和捕获
当一个事件发生时 —— 发生该事件的嵌套最深的元素被标记为“目标元素”(event.target
)。
- 然后,事件从文档根节点向下移动到
event.target
,并在途中调用分配了addEventListener(..., true)
的处理程序(true
是{capture: true}
的一个简写形式)。 - 然后,在目标元素自身上调用处理程序。
- 然后,事件从
event.target
冒泡到根,调用使用on<event>
、HTML 特性(attribute)和没有第三个参数的,或者第三个参数为false/{capture:false}
的addEventListener
分配的处理程序。
每个处理程序都可以访问 event
对象的属性:
event.target
—— 引发事件的层级最深的元素。event.currentTarget
(=this
)—— 处理事件的当前元素(具有处理程序的元素)event.eventPhase
—— 当前阶段(capturing=1,target=2,bubbling=3)。
任何事件处理程序都可以通过调用 event.stopPropagation()
来停止事件,但不建议这样做,因为我们不确定是否确实不需要冒泡上来的事件,也许是用于完全不同的事情。
事件委托
捕获和冒泡允许我们实现一种被称为 事件委托 的强大的事件处理模式。
这个想法是,如果我们有许多以类似方式处理的元素,那么就不必为每个元素分配一个处理程序 —— 而是将单个处理程序放在它们的共同祖先上。
在处理程序中,我们获取 event.target
以查看事件实际发生的位置并进行处理。
当我们将事件处理程序分配给
document
对象时,我们应该始终使用addEventListener
,而不是document.on<event>
,因为后者会引起冲突:新的处理程序会覆盖旧的处理程序。
好处:
- 简化初始化并节省内存:无需添加许多处理程序。
- 更少的代码:添加或移除元素时,无需添加/移除处理程序。
- DOM 修改 :我们可以使用
innerHTML
等,来批量添加/移除元素。
事件委托也有其局限性:
- 首先,事件必须冒泡。而有些事件不会冒泡。此外,低级别的处理程序不应该使用
event.stopPropagation()
。 其次,委托可能会增加 CPU 负载,因为容器级别的处理程序会对容器中任意位置的事件做出反应,而不管我们是否对该事件感兴趣。但是,通常负载可以忽略不计,所以我们不考虑它。
浏览器默认行为
许多事件会自动触发浏览器执行某些行为。
有两种方式来告诉浏览器我们不希望它执行默认行为:主流的方式是使用
event
对象。有一个event.preventDefault()
方法。- 如果处理程序是使用
on<event>
(而不是addEventListener
)分配的,那返回false
也同样有效。