Web浏览器的事件类型——HTML事件| 8月更文挑战

557 阅读4分钟

这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战

HTML5 详尽地列出了浏览器支持的所有事件。下面会介绍浏览器较好支持的事件,但也并不是所有浏览器支持。

1. contextmenu 事件

contextmenu 事件,以专门用于表示何时该显示上下文菜单,从而允许开发者取消默认的上下文菜单并提供自定义菜单。contextmenu 事件冒泡,因此只要给 document 指定一个事件处理程序就可以处理页面上的所有同类事件。contextmenu 事件应该算一种鼠标事件,因此 event 对象上的很多属性都与光标位置有关。来看下面的例子:

<!DOCTYPE html>
<html>
  <head>
    <title>ContextMenu Event Example</title>
  </head>
  <body>
    <div id="myDiv">
      Right click or Ctrl+click me to get a custom context menu. Click anywhere else to get the default context menu.
    </div>
    <ul
      id="myMenu"
      style="position: absolute; visibility: hidden; background-color: silver"
    >
      <li><a href="http://www.somewhere.com"> somewhere</a></li>
      <li><a href="http://www.wrox.com">Wrox site</a></li>
      <li><a href="http://www.somewhere-else.com">somewhere-else</a></li>
    </ul>
    <script>
      window.addEventListener("load", (event) => {
        let div = document.getElementById("myDiv");
        div.addEventListener("contextmenu", (event) => {
          event.preventDefault(); // 阻止默认菜单的展示
          // 展示自定义的菜单
          let menu = document.getElementById("myMenu");
          menu.style.left = event.clientX + "px";
          menu.style.top = event.clientY + "px";
          menu.style.visibility = "visible";
        });
        document.addEventListener("click", (event) => {
          document.getElementById("myMenu").style.visibility = "hidden";
        });
      });
    </script>
  </body>
</html>

2. beforeunload 事件

beforeunload 事件会在 window 上触发,用意是给开发者提供阻止页面被卸载的机会。这个事件会在页面即将从浏览器中卸载时触发,我们可以在页面被卸载的时候做一些我们需要做的事情。当然一般我们是不希望用户关闭页面的,所以我们会给提示框。

类似下面的代码:

window.addEventListener("beforeunload", (event) => {
  let message = "I'm really going to miss you if you go.";
  event.returnValue = message; // 针对IE和Firefox
  return message; // 针对safari和chrome
}); 

3. DOMContentLoaded 事件

windowload 事件会在页面完全加载后触发。而 DOMContentLoaded 事件会在 DOM 树构建完成后立即触发,不用等待图片、JavaScript 文件、CSS 文件或其他资源加载完成。相对于 load 事件,DOMContentLoaded 可以让开发者在外部资源下载的同时就能指定事件处理程序,从而让用户能够更快地与页面交互。

下面是一个简单的例子:

document.addEventListener("DOMContentLoaded", (event) => {
  console.log("Content loaded");
});

DOMContentLoaded 事件的 event 对象中不包含任何额外信息(除了 target 等于 document)。

4. readystatechange 事件

支持 readystatechange 事件的每个对象都有一个 readyState 属性,该属性具有一个以下列出的可能的字符串值。

  • uninitialized: 对象存在并尚未初始化。
  • loading: 对象正在加载数据。
  • loaded: 对象已经加载完数据。
  • interactive: 对象可以交互,但尚未加载完成。
  • complete: 对象加载完成。

document 上使用时,值为interactivereadyState 首先会触发 readystatechange 事件,时机类似于 DOMContentLoaded。进入交互阶段,意味着 DOM 树已加载完成,因而可以安全地交互了。下面是一个使用例子:

document.addEventListener("readystatechange", (event) => {
  if (document.readyState == "interactive") {
    console.log("Content loaded");
  }
}); 

在包含特别多或较大外部资源的页面中,交互阶段会在 load 事件触发前先触发。而在包含较少且较小外部资源的页面中,这个 readystatechange 事件有可能在 load 事件触发后才触发。

document.addEventListener("readystatechange", (event) => {
  if (
      document.readyState == "interactive" ||
      document.readyState == "complete"
    ) {
      document.removeEventListener("readystatechange", arguments.callee);
      console.log("Content loaded");
  }
});

先检测 readyState 的状态是不是可交互或者已完成,如果是的话,就移除事件监听。注意,因为这里的事件处理程序是匿名函数,所以使用了 arguments.callee 作为函数指针。

MDN 对这个事件是这样描述的:

当文档的 readyState 属性发生改变时,会触发 readystatechange 事件。

在给出的例子中,是对 loadreadystatechangeDOMContentLoaded 这三个事件的先后顺序做了个测试。

执行后的结果依次是:

readystate: interactive
DOMContentLoaded
readystate: complete
load

5. pageshow 与 pagehide 事件

pageshow:其会在页面显示时触发,无论是否来自往返缓存。在新加载的页面上,pageshow 会在 load 事件之后触发;在来自往返缓存的页面上,pageshow 会在页面状态完全恢复后触发。

下面来看一个例子:

(function() {
  let showCount = 0;
  window.addEventListener("load", () => {
    console.log("Load fired");
  });
  window.addEventListener("pageshow", () => {
    showCount++;
    console.log(`Show has been fired ${showCount} times.`, `Persisted? ${event.persisted}`); // persisted: 如果页面存储在了往返缓存中就是 true,否则就是 false。
 });
})(); 

这边用了一个闭包,把每次进入页面的 showCount 记录下来。每次进入页面都会记录进入的次数。除非刷新页面。

pageshow 对应的事件是 pagehide,这个事件会在页面从浏览器中卸载后,在 unload 事件之前触发。

window.addEventListener("pagehide", (event) => {
  console.log("Hiding. Persisted? " + event.persisted);
}); 

pageshow 事件来说,persistedtrue 表示页面是从往返缓存中加载的;而对 pagehide 事件来说,persistedtrue 表示页面在卸载之后会被保存在往返缓存中。

6. hashchange 事件

HTML5 增加了 hashchange 事件,用于在 URL 散列值(URL 最后#后面的部分)发生变化时通知开发者。这是因为开发者经常在 Ajax 应用程序中使用 URL 散列值存储状态信息或路由导航信息。

event 对象有两个新属性:oldURLnewURL。这两个属性分别保存变化前后的 URL,而且是包含散列值的完整 URL。下面的例子展示了如何获取变化前后的 URL

window.addEventListener("hashchange", (event) => {
  console.log(`Old URL: ${event.oldURL}, New URL: ${event.newURL}`);
});
// 如果想确定当前的散列值,最好使用 location 对象:
window.addEventListener("hashchange", (event) => {
  console.log(`Current hash: ${location.hash}`);
}); 

7. 引用

[1] JavaScript高级程序设计(第4版)