应使用 window.navigator.onLine 和 online/offline 事件监听网络状态,配合 layer.open() 实现非阻塞顶部横幅提示,并通过心跳请求验证真实连通性,避免假在线与横幅堆叠问题。

监听网络状态变化用 window.navigator.onLine
浏览器原生提供 navigator.onLine 属性和 online/offline 事件,Layui 本身不封装网络状态逻辑,得自己监听。注意:这个 API 只能判断浏览器是否认为联网(比如禁用网卡或断开 Wi-Fi 会触发 offline),但无法检测到「已连 Wi-Fi 却无外网」或「DNS 失败」「网关超时」等真实业务级断网——它只是粗粒度的连接开关信号。
实操建议:
- 在页面加载后立即检查
navigator.onLine初始值,避免首次打开就离线却没提示 - 绑定
window.addEventListener('offline', ...)和window.addEventListener('online', ...),不要只依赖定时轮询 - 避免在
offline回调里直接调用 Layui 的layer.msg()或layer.alert(),它们是模态弹窗,打断用户操作且无法自动关闭;横幅需非阻塞、可自动收起
用 layer.open() 模拟横幅并控制样式与生命周期
Layui 的 layer.open() 支持自定义内容和样式,适合做顶部横幅。关键不是用 layer.msg()(它是底部小 toast),而是用 type: 1(页面层)+ area + offset 定位到顶部,并手动设 anim: -1 关闭动画、time: 3000 自动关闭。
示例代码片段:
let offlineLayer = null;
function showOfflineBanner() {
if (offlineLayer) return; // 防重复触发
offlineLayer = layer.open({
type: 1,
title: false,
closeBtn: 0,
offset: 't',
area: ['100%', '42px'],
anim: -1,
time: 3000,
shade: false,
content: '<div style="background:#f60;color:#fff;text-align:center;line-height:42px;font-size:14px;">⚠️ 网络连接已断开,请检查网络</div>',
end: () => { offlineLayer = null; }
});
}
window.addEventListener('offline', showOfflineBanner);
注意:layer.open() 默认会加阴影和边框,必须显式设 shade: false 和 closeBtn: 0 才像横幅;offset: 't' 是顶部定位,但若页面有固定头部,可能需要 offset: '0px' 并配合 style="top: 0;" 更精准。
处理「假在线」问题:发心跳请求验证真实连通性
navigator.onLine 返回 true 不代表能访问你的后端。常见场景:本地开发时 localhost 正常,但部署后 CDN 域名被屏蔽、或接口域名 DNS 解析失败,此时 onLine 仍为 true,但所有 $.ajax 都会超时。
实操建议:
- 在应用启动后,用
$.ajax({ url: '/api/health', timeout: 3000 })发一个轻量心跳(后端返回200 OK即可),失败则手动触发横幅 - 后续每次接口请求前,不重复发心跳;但若连续 2 次请求因
statusText === 'timeout'或status === 0失败,再触发横幅并暂停自动重试 - 心跳接口必须静态、无鉴权、不走代理(比如直接指向同域
/healthz),否则会形成死循环
避免横幅堆叠和误关闭
用户快速切网、重连多次时,容易因事件触发频率高导致多个横幅叠加,或刚显示就被另一个 online 事件清掉。
关键控制点:
- 用单例变量
offlineLayer记录当前横幅 ID,每次触发前先if (offlineLayer) layer.close(offlineLayer) - 收到
online事件时,不要立刻关闭横幅(用户可能还没看到),而是延迟 500ms 关闭,或只清除定时器、让横幅自然消失 - 如果横幅被用户手动点击关闭,要同步置空
offlineLayer,否则下次断网不会重显 - 移动端 Safari 对
offline事件支持不稳定,建议加一个 10 秒级的兜底轮询(仅当navigator.onLine === true时才轮询)
网络状态横幅真正的难点不在显示,而在「什么时候该显示」和「什么时候不该显示」——尤其是混合了前端缓存、PWA、代理环境之后,navigator.onLine 的真假边界非常模糊。先跑通基础监听,再根据实际部署环境补心跳和兜底逻辑。











