Navigator 接口表示用户代理的状态和标识。它允许脚本查询它和注册自己进行一些活动。
onLine
表明浏览器是否联网
if (navigator.onLine) {
console.log("online");
} else {
console.log("offline");
}
window.addEventListener("offline", (e) => {
console.log("offline");
});
window.addEventListener("online", (e) => {
console.log("online");
});
serviceWorker
ServiceWorkerContainer 对象用于提供注册、删除、更新。
if ('serviceWorker' in navigator) {
// Supported!
}
userAgent
User-Agent 首部包含了一个特征字符串,用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。
可以修改伪装, 比较混乱
User-Agent: Mozilla/<version> (<system-information>) <platform> (<platform-details>) <extensions>
-
Mozilla/[version]浏览器名/版本,没有意义 -
<system-information>分号隔开 -
<platform> (<platform-details>)浏览器渲染引擎 -
<extensions>扩展字段采用空格进行分隔- Chrome:Chrome/版本号
- Safari:Safari/版本号 (历史原因,chrome浏览器后面也会带safari字段)
- Version:Version/版本号 系统版本号
- Mobile:移动设备标识,一般指内部版本号,苹果设备会带版本号,安卓设备不含版本号
使用 Bowser 简化判断
const browserObject = bowser.parse(window.navigator.userAgent);
const { browser, os } = browserObject;
const { name: browserName, version: browserVersion } = browser;
const { name: osName, versionName: osVersionName } = os;
console.log(
`${browserName} ${browserVersion} ${osName} ${osVersionName}`
);
geolocation
可访问设备的地理位位置信息
navigator.geolocation.getCurrentPosition(success, error, options)
-
success
pos.coords
- latitude 纬度
- longitude 经度
- accuracy 精确
-
error
- code
- message
-
options
- enableHighAccuracy 是否使用其最高精度来表示结果
- timeout 超时时间
- maximumAge 0 不使用缓存
var options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
};
function success(pos) {
var crd = pos.coords;
console.log('Your current position is:');
console.log('Latitude : ' + crd.latitude);
console.log('Longitude: ' + crd.longitude);
console.log('More or less ' + crd.accuracy + ' meters.');
};
function error(err) {
console.warn('ERROR(' + err.code + '): ' + err.message);
};
navigator.geolocation.getCurrentPosition(success, error, options);
sendBeacon
navigator.sendBeacon(url, data) 方法可用于通过 HTTP POST 将少量数据异步传输到 Web 服务器。
它主要用于将统计数据发送到 Web 服务器,同时避免了用传统技术发送分析数据的一些问题。
在文档卸载期间发送数据一直是一个困难。因为用户代理通常会忽略在 unload 事件处理器中产生的异步 XMLHttpRequest。
过去,为了解决这个问题,统计和诊断代码通常要在
- 发起一个同步
XMLHttpRequest来发送数据。 - 创建一个
<img>元素并设置src,大部分用户代理会延迟卸载(unload)文档以加载图像。 - 创建一个几秒的 no-op 循环。
document.addEventListener("visibilitychange", function logData() {
if (document.visibilityState === "hidden") {
navigator.sendBeacon("/log", analyticsData);
}
});
window.addEventListener(
"pagehide",
(event) => {
if (event.persisted) {
/* the page isn't being discarded, so it can be reused later */
}
},
false,
);
避免使用 unload 和 beforeunload
- 用户加载了网页并与其交互。
- 完成浏览后,用户切换到了其他应用程序,而不是关闭选项卡。
- 随后,用户通过手机的应用管理器关闭了浏览器应用。
unload事件与现代浏览器实现的往返缓存(bfcache)不兼容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Navigator.sendBeacon</title>
</head>
<body onload="analytics('start')" onunload="analytics('end')">
<a id="target" href="https://baidu.com">click</a>
<script>
function log() {
let xhr = new XMLHttpRequest();
xhr.open("post", "/log", true);
xhr.setRequestHeader(
"Content-Type",
"application/x-www-form-urlencoded"
);
xhr.send("foo=bar");
}
window.addEventListener("unload", function (event) {
log();
// a time-consuming operation
for (let i = 1; i < 10000; i++) {
for (let m = 1; m < 10000; m++) {
continue;
}
}
});
const clickTime = 35000;
const theLink = document.getElementById("target");
theLink.addEventListener("click", function (event) {
event.preventDefault();
log();
setTimeout(function () {
window.location.href = theLink.getAttribute("href");
}, clickTime);
});
window.addEventListener("unload", logData, false);
function logData() {
navigator.sendBeacon("/log", "foo=bar");
}
function analytics(state) {
if (!navigator.sendBeacon) return;
var URL = "http://example.com/analytics";
var data = "state=" + state + "&location=" + window.location;
navigator.sendBeacon(URL, data);
}
</script>
</body>
</html>