文章目录
90%的前端不知道浏览器偷偷做了什么?(14个监听事件暴露的交互秘密)
一、窗口生命周期事件
1. load 事件
- 功能:当整个页面(包括所有依赖资源如图片、样式表、脚本等)完全加载完成后触发。
- 用法:监听页面及所有资源加载完成的时刻,常用于初始化需要完整资源的操作。
- 代码示例:
window.addEventListener('load', () => {
console.log('页面及所有资源加载完成');
// 例如:初始化依赖图片尺寸的组件
initImageGallery();
});
- 注意事项:
- 触发时机较晚,需等待所有资源加载,不适合需要尽早执行的逻辑
- 若资源加载失败(如图片404),仍会触发此事件
2. DOMContentLoaded 事件
- 功能:当HTML文档被完全解析,DOM树构建完成后触发,无需等待样式表、图片等资源加载。
- 用法:适合需要DOM结构就绪后立即执行的操作(如绑定事件、初始化UI)。
- 代码示例:
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM解析完成,可操作DOM元素');
// 例如:绑定按钮点击事件
document.getElementById('submitBtn').addEventListener('click', handleSubmit);
});
- 注意事项:
- 与
load的核心区别:不等待外部资源,仅需DOM就绪 - 若存在同步JavaScript阻塞DOM解析,会延迟此事件触发
- 与
3. unload 事件
- 功能:当页面正在被卸载(如关闭标签页、导航到新页面)时触发。
- 用法:常用于清理资源、记录用户离开时间等操作。
- 代码示例:
window.addEventListener('unload', () => {
console.log('页面即将卸载');
// 例如:发送用户停留时间统计(可靠性较低)
navigator.sendBeacon('/api/user-leave', JSON.stringify({ duration: getStayTime() }));
});
- 注意事项:
- 执行时间有限制,复杂操作可能被浏览器忽略
- 不建议使用
alert()等阻塞性API sendBeacon()是推荐的异步数据提交方式,比XMLHttpRequest更可靠
4. beforeunload 事件
- 功能:在页面即将卸载前触发,可用于提示用户保存未完成的操作。
- 用法:常用于防止用户意外关闭页面(如表单未提交)。
- 代码示例:
window.addEventListener('beforeunload', (e) => {
// 取消事件的默认行为
e.preventDefault();
// Chrome需要设置returnValue
e.returnValue = '';
// 浏览器可能显示自定义提示(受浏览器安全限制)
return '您有未保存的内容,确定要离开吗?';
});
- 注意事项:
- 自定义提示文本在多数现代浏览器中会被忽略,显示浏览器默认文本
- 仅当页面有用户交互(如输入内容)时,提示才可能生效
- 过度使用会影响用户体验,仅在必要时使用
二、窗口尺寸与滚动事件
5. resize 事件
- 功能:当浏览器窗口尺寸发生变化(包括最大化、最小化、拖拽边框)时触发。
- 用法:用于响应式布局调整、重新计算元素位置或尺寸。
- 代码示例:
// 节流函数优化性能
function throttle(func, delay = 100) {
let timer = null;
return (...args) => {
if (!timer) {
timer = setTimeout(() => {
func.apply(this, args);
timer = null;
}, delay);
}
};
}
window.addEventListener('resize', throttle(() => {
console.log(`窗口尺寸: ${window.innerWidth}x${window.innerHeight}`);
// 例如:调整图表尺寸以适应窗口
resizeChart();
}));
- 注意事项:
- 会频繁触发(如拖拽窗口时),必须使用节流(throttle)优化性能
- 移动设备旋转屏幕时也会触发
- 可通过
window.innerWidth/innerHeight获取当前窗口尺寸
6. scroll 事件
- 功能:当页面或元素发生滚动时触发(窗体滚动监听的是
window对象)。 - 用法:用于实现滚动加载、显示/隐藏回到顶部按钮、导航栏样式变化等。
- 代码示例:
window.addEventListener('scroll', throttle(() => {
const scrollY = window.scrollY;
console.log(`滚动距离: ${scrollY}px`);
// 示例1:滚动超过300px显示回到顶部按钮
const backToTopBtn = document.getElementById('backToTop');
backToTopBtn.style.display = scrollY > 300 ? 'block' : 'none';
// 示例2:滚动到指定区域时激活导航高亮
highlightNavByScroll();
}));
- 注意事项:
- 滚动时高频触发,需使用节流优化性能
- 避免在事件处理中执行复杂DOM操作(如大量重排重绘)
- 可通过
window.scrollY/scrollX获取滚动距离
三、窗口焦点与状态事件
7. focus 事件
- 功能:当浏览器窗口或标签页获得焦点(用户切换回该窗口)时触发。
- 用法:用于恢复暂停的任务(如视频播放、定时器)、刷新数据等。
- 代码示例:
window.addEventListener('focus', () => {
console.log('窗口获得焦点');
// 例如:恢复视频播放
videoElement.play();
// 例如:刷新实时数据
refreshRealTimeData();
});
- 注意事项:
- 与元素的
focus事件不同,此处是窗口级别的焦点 - 可通过
document.hasFocus()检查窗口是否处于焦点状态
- 与元素的
8. blur 事件
- 功能:当浏览器窗口或标签页失去焦点(用户切换到其他窗口)时触发。
- 用法:用于暂停消耗资源的操作(如动画、视频)、保存临时状态等。
- 代码示例:
window.addEventListener('blur', () => {
console.log('窗口失去焦点');
// 例如:暂停视频播放
videoElement.pause();
// 例如:保存当前编辑状态
saveDraft();
});
- 注意事项:
- 窗口最小化时也会触发
- 避免在该事件中执行耗时操作,可能影响用户体验
9. online 事件
- 功能:当浏览器从离线状态切换到在线状态时触发。
- 用法:用于恢复网络连接后同步数据、重新加载资源等。
- 代码示例:
window.addEventListener('online', () => {
console.log('网络已连接');
// 例如:同步离线时缓存的数据
syncOfflineData();
// 例如:显示在线状态提示
showNotification('已恢复网络连接', 'success');
});
- 注意事项:
- 依赖
navigator.onLine属性判断网络状态(存在局限性,可能误判) - 最好结合实际接口请求验证网络可用性
- 依赖
10. offline 事件
- 功能:当浏览器从在线状态切换到离线状态时触发。
- 用法:用于提示用户网络中断、切换到离线模式、缓存关键资源等。
- 代码示例:
window.addEventListener('offline', () => {
console.log('网络已断开');
// 例如:提示用户当前处于离线状态
showNotification('网络连接已中断,部分功能可能受限', 'error');
// 例如:缓存后续可能需要的资源
cacheCriticalResources();
});
- 注意事项:
- 与
online事件配合使用,实现离线优先(Offline First)策略 - 可结合Service Worker增强离线体验
- 与
四、导航与历史事件
11. popstate 事件
- 功能:当用户点击浏览器前进/后退按钮,或通过
history.back()/forward()/go()修改历史记录时触发。 - 用法:单页应用(SPA)中用于监听路由变化,更新页面内容。
- 代码示例:
// 监听历史记录变化
window.addEventListener('popstate', (e) => {
console.log('历史记录变化', e.state);
// 例如:根据当前URL更新页面内容
updatePageByUrl(window.location.pathname);
});
// 示例:添加新历史记录(不会触发popstate)
history.pushState({ page: 'about' }, '关于页', '/about');
- 注意事项:
- 调用
history.pushState()或replaceState()不会触发此事件 - 事件对象的
state属性包含调用pushState时传入的状态数据 - 需配合
historyAPI手动管理路由状态
- 调用
12. hashchange 事件
- 功能:当URL中的哈希部分(
#后面的内容)发生变化时触发。 - 用法:用于实现基于哈希的路由(无需后端支持)、锚点导航等。
- 代码示例:
window.addEventListener('hashchange', (e) => {
console.log('哈希变化:', {
oldURL: e.oldURL,
newURL: e.newURL,
newHash: window.location.hash
});
// 例如:根据哈希值显示对应内容
showContentByHash(window.location.hash);
});
// 示例:修改哈希(会触发hashchange)
// window.location.hash = 'section1';
- 注意事项:
- 哈希变化会添加到浏览器历史记录,用户可通过前进/后退导航
- 适合简单路由场景,复杂场景建议使用
historyAPI - 哈希值不会发送到服务器,适合前端独立处理的路由
五、其他重要事件
13. visibilitychange 事件
- 功能:当页面可见性状态变化时触发(如用户切换标签页、最小化窗口)。
- 用法:用于暂停/恢复视频播放、调整通知频率、优化性能等。
- 代码示例:
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
console.log('页面变为可见');
// 例如:恢复广告轮播
resumeAdCarousel();
} else {
console.log('页面变为不可见');
// 例如:暂停背景音乐
pauseBackgroundMusic();
}
});
- 注意事项:
- 依赖
document.visibilityState属性(值为visible/hidden/prerender等) - 比
focus/blur更精准地反映页面是否被用户看到
- 依赖
14. orientationchange 事件
- 功能:当移动设备屏幕旋转(横屏/竖屏切换)时触发。
- 用法:用于适配不同屏幕方向的布局调整。
- 代码示例:
window.addEventListener('orientationchange', () => {
const orientation = window.orientation;
console.log('屏幕方向变化:', orientation); // 0:竖屏, 90/-90:横屏
if (Math.abs(orientation) === 90) {
// 横屏处理
document.body.classList.add('landscape');
} else {
// 竖屏处理
document.body.classList.remove('landscape');
}
});
- 注意事项:
- 主要用于移动设备,桌面浏览器通常不支持
- 可结合
resize事件增强兼容性 - 现代浏览器推荐使用
screen.orientationAPI配合change事件
注意事项总结
-
性能优化:
高频触发事件(resize、scroll)必须使用节流(throttle)控制执行频率,避免频繁DOM操作导致页面卡顿。 -
事件解绑:
在单页应用或组件卸载时,需通过removeEventListener移除事件监听,防止内存泄漏(特别是使用匿名函数时需保存引用)。 -
兼容性处理:
部分事件(如beforeunload提示文本、orientationchange)在不同浏览器中行为存在差异,需测试并添加兼容代码。 -
用户体验:
避免滥用beforeunload等可能打断用户操作的事件;网络状态变化时提供清晰的用户反馈。 -
时机选择:
根据需求选择合适的事件(如DOM操作优先用DOMContentLoaded,依赖资源用load)。

5434

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



