HTML特性

  1. <script>
  2. function countRabbits() {
  3. for(let i=1; i<=3; i++) {
  4. alert("Rabbit number " + i);
  5. }
  6. }
  7. </script>
  8. <input type="button" onclick="countRabbits()" value="Count rabbits!">
  • HTML 特性名是大小写不敏感的,所以 ONCLICKonClick 以及 onCLICK 都一样可以运行。但是特性通常是小写的:onclick
  • 在HTML特性中,传给onclick的函数需要括号,浏览器将会使用 特性中的内容 创建一个处理程序。所以,标记(markup)会生成下面这个属性:

    1. button.onclick = function() {
    2. countRabbits(); // <-- 特性(attribute)中的内容变到了这里
    3. };

    DOM属性

    1. <input id="elem" type="button" value="Click me">
    2. <script>
    3. elem.onclick = function() {
    4. alert('Thank you');
    5. };
    6. </script>
  • DOM属性区分大小写

  • 要移除一个处理程序 —— 赋值 elem.onclick = null
  • DOM属性只能绑定一个处理程序

    addEventListener

    可以为一个事件分配多个处理程序
    1. element.addEventListener(event, handler[, options]);

    removeEventListener

    用于移除处理程序,但必须移除相同的处理程序 ```javascript function handler() { alert( ‘Thanks!’ ); }

input.addEventListener(“click”, handler); // …. input.removeEventListener(“click”, handler);

  1. <a name="C6k5u"></a>
  2. ### 事件对象
  3. 当事件发生时,浏览器会创建一个 **`event` 对象**,将详细信息放入其中,并将其作为参数传递给处理程序。
  4. ```javascript
  5. <input type="button" value="Click me" id="elem">
  6. <script>
  7. elem.onclick = function(event) {
  8. // 显示事件类型、元素和点击的坐标
  9. alert(event.type + " at " + event.currentTarget);
  10. alert("Coordinates: " + event.clientX + ":" + event.clientY);
  11. };
  12. </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 也同样有效。