你以为
click和keydown就是 DOM 事件的全部?那可太天真了。
在现代 Web 开发中,我们习惯了监听用户点击、输入、滚动等“常规操作”,但浏览器其实悄悄提供了许多鲜为人知却功能强大的 DOM 事件。它们或许不常出现在日常业务代码中,但在特定场景下,却能成为提升用户体验、优化性能甚至实现关键功能的“秘密武器”。
今天,我们就来揭开这些冷门但实用的 DOM 事件的神秘面纱:
beforeprint / afterprint、contextmenu、online / offline、pageshow / pagehide、select、storage。
准备好了吗?让我们一起潜入浏览器事件系统的“暗流”!
🖨️ 打印前后控制:beforeprint 与 afterprint
当你调用 window.print() 或用户通过菜单触发打印时,浏览器会依次触发这两个事件:
beforeprint:在打印对话框弹出之前触发。afterprint:在用户关闭打印对话框(无论是否真的打印)之后触发。
应用场景
- 临时隐藏非打印内容:比如广告、导航栏。
- 动态调整样式:为打印专门生成适合纸张的布局。
- 记录打印行为(用于分析或审计)。
示例代码
window.addEventListener('beforeprint', () => {
document.body.classList.add('printing');
});
window.addEventListener('afterprint', () => {
document.body.classList.remove('printing');
});
配合 CSS:
@media print {
.no-print { display: none; }
}
.printing .ads-banner {
display: none !important;
}
💡 注意:某些浏览器(如 Safari)对这两个事件的支持有限,建议结合
@media print媒体查询做双重保障。
🖱️ 右键菜单拦截:contextmenu
当用户右键点击页面元素时,会触发 contextmenu 事件。默认行为是弹出浏览器原生菜单,但你可以阻止它并自定义菜单。
典型用途
- 实现富文本编辑器中的右键功能(如复制、粘贴、格式化)。
- 游戏或绘图应用中的上下文操作。
- 防止用户“偷看”页面源码(虽然效果有限 😅)。
示例
document.addEventListener('contextmenu', (e) => {
e.preventDefault(); // 阻止默认菜单
showCustomMenu(e.clientX, e.clientY); // 自定义菜单
});
⚠️ 注意:不要滥用!完全禁用右键可能损害无障碍体验。合理使用,尊重用户习惯。
🌐 网络状态感知:online 与 offline
这两个事件由 window 对象触发,反映设备的网络连接状态变化:
online:设备重新联网时触发。offline:设备断网时触发。
使用技巧
- 构建离线优先(Offline-First)应用。
- 在断网时自动切换到缓存模式,并提示用户。
- 网络恢复后自动同步未提交的数据。
示例
window.addEventListener('offline', () => {
showToast('网络已断开,请检查连接');
enableOfflineMode();
});
window.addEventListener('online', () => {
showToast('网络已恢复');
syncPendingData();
});
🔍 补充:可通过
navigator.onLine属性实时获取当前网络状态。
👁️ 页面可见性之外:pageshow 与 pagehide
你可能熟悉 visibilitychange,但 pageshow 和 pagehide 是更底层的页面生命周期事件,尤其在处理往返缓存(bfcache) 时至关重要。
pageshow:页面加载或从 bfcache 恢复时触发。pagehide:页面卸载或进入 bfcache 前触发。
关键区别
load事件在从 bfcache 恢复时不会再次触发,但pageshow会。pagehide的event.persisted属性为true表示页面将被缓存(而非彻底销毁)。
应用场景
- 重置动画或定时器(避免从缓存恢复时状态错乱)。
- 记录用户实际离开页面的时间(比
unload更可靠)。
示例
window.addEventListener('pageshow', (event) => {
if (event.persisted) {
console.log('页面从 bfcache 恢复');
resetTimers();
}
});
window.addEventListener('pagehide', (event) => {
if (event.persisted) {
console.log('页面将进入 bfcache');
} else {
console.log('页面将被彻底卸载');
}
});
📌 提示:现代浏览器越来越依赖 bfcache 提升性能,理解这两个事件对构建健壮应用非常重要。
✏️ 文本选中监听:select
当用户在 <input> 或 <textarea> 中选中文本时触发 select 事件。
常见用途
- 自动复制选中内容(如代码片段网站)。
- 高亮显示选区统计(字数、行数等)。
- 触发上下文操作(如“翻译选中文字”)。
注意事项
- 仅在可编辑元素上有效。
- 不适用于普通段落(
<p>)中的文本选中。若需监听任意选中,应使用selectionchange事件(属于 Selection API)。
示例
document.querySelector('#code-input').addEventListener('select', (e) => {
const selectedText = e.target.value.substring(
e.target.selectionStart,
e.target.selectionEnd
);
console.log('选中内容:', selectedText);
});
🗃️ 跨标签页通信:storage
当其他同源页面调用 localStorage.setItem() 修改存储时,当前页面会收到 storage 事件。
这是跨标签页通信的“官方通道”!
- 不需要轮询。
- 自动同步,安全可靠(同源策略保护)。
事件对象包含
key:被修改的键。newValue/oldValue:新旧值。url:触发变更的页面 URL。storageArea:即localStorage对象。
示例:多标签页登录状态同步
window.addEventListener('storage', (e) => {
if (e.key === 'authToken') {
if (!e.newValue) {
// 用户在其他标签页登出
redirectToLogin();
}
}
});
🔐 安全提示:不要在
localStorage中存储敏感信息(如密码),但用于 token 同步是常见实践。
总结:冷门 ≠ 无用,而是“高阶武器”
这些不常被提及的 DOM 事件,看似边缘,实则蕴含强大能力:
| 事件 | 核心价值 |
|---|---|
beforeprint / afterprint | 精准控制打印体验 |
contextmenu | 自定义交互入口 |
online / offline | 构建离线健壮性 |
pageshow / pagehide | 掌控 bfcache 生命周期 |
readystatechange | 细粒度加载控制 |
select | 响应用户文本操作 |
storage | 跨标签页状态同步 |
真正的高手,不仅会用热门 API,更懂得在恰当时机祭出这些“冷兵器”。
下次当你面对一个棘手的交互需求时,不妨回头看看这些被遗忘的事件——也许,答案就藏在其中。
🌟 思考题:你的项目中是否曾因不知道某个事件而绕了远路?欢迎在评论区分享你的“顿悟时刻”!
延伸阅读建议:
- MDN Web Docs: Window: beforeprint event
- Google Web Fundamentals: Back/forward cache
- WHATWG Storage Standard: storage event
别让知识停留在“听说过”,动手试试,让这些事件成为你工具箱里的新利器!

2763

被折叠的 条评论
为什么被折叠?



