现代浏览器已默认禁用ping属性,需用fetch()或sendbeacon()替代:监听click、preventdefault、发请求(keepalive或formdata)、再跳转,并处理超时、节流、csp及跨域限制。

ping 属性在现代浏览器中基本失效
Chrome 117+、Edge 117+、Firefox 119+ 已默认禁用 ping 属性的网络请求,点击 <a ping="https://log.example.com"></a> 不会发出任何请求。这是出于隐私保护(防止跨站跟踪)和安全策略(避免隐蔽 beacon)的主动限制,不是 bug,也无需“修复”。
替代方案:用 fetch() + preventDefault() 手动实现
必须拦截原生跳转,先发日志再导航。关键点是:不能依赖 ping 的异步“不阻塞”,而要自己控制时序,且需处理失败降级。
- 监听
click事件,调用event.preventDefault() - 用
fetch(url, { method: 'POST', body: JSON.stringify(...), keepalive: true })发送日志(keepalive: true确保页面卸载前完成) - 成功后用
window.location.href = link.href或link.target === '_blank' ? window.open(...) : ...模拟跳转 - 失败时建议 fallback:直接跳转(不丢用户),或退化为
navigator.sendBeacon()(兼容性更好但只支持 POST + FormData)
sendBeacon() 更可靠但限制多
比 fetch(..., { keepalive }) 兼容性更好(IE11+、所有现代浏览器都支持),但要求 payload 是 ArrayBuffer、Blob 或 FormData,且无法获取响应结果。
- 构造日志数据必须用
new FormData()或new Blob([JSON.stringify(...)], {type: 'application/json'}) - 调用
navigator.sendBeacon('https://log.example.com', formData)后立即跳转,无需等待 - 注意:Safari 对
sendBeacon()的 URL 有同源限制更严格,跨域需服务端配Access-Control-Allow-Origin: *且允许Content-Type头
真实部署时最容易忽略的坑
日志收集本身会失败,但用户不该感知——跳转延迟、白屏、重复发送、CSP 阻断,都是线上高频问题。
- CSP 策略必须显式允许日志域名:
connect-src https://log.example.com,否则 fetch/sendBeacon 直接被拦截且无报错 - 不要在
click里 await fetch;应 Promise.race([fetch(...), new Promise(r => setTimeout(r, 500))]) 加超时,防卡死 - 同一个链接多次快速点击(如手抖)会导致重复日志,建议加简单节流:
if (link.__beaconSent) return; link.__beaconSent = true - SPA 应用(React/Vue)别直接绑原生 click,要用路由拦截(如
beforeEach)统一打点,否则 a 标签可能被框架劫持不触发原生事件
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











