几个很实用但是又比较冷门的 Web API 极其极简演示
时间:2026-1-25 23:17 作者:独元殇 分类: 前端技术
[toc]
前言
API(应用程序编程接口),就像是小国家与小国家之间沟通的桥梁。在编程里,就是模块与模块、软件与软件之间沟通的路子。
今天我来分享几个比较少用但 你肯定很有想用过 的 Web Api。
现在 AI 来了,可能我们很少去关注程序的细节了,但是我们的眼界和过去古法编程一样,仍然是:知道的越多更重要,知道了就是「学会」了,反正有文档用起来就是无复用成本,毕竟我们的很多问题是我们不知道我们不知道什么....
这个 Web API ,是用户和 浏览器 之间沟通的桥梁,一般是 JavaScript 在使用,也可以被 python go rust 等等使用。
之前,我们可能脍炙人口下面这些 API:
Geolocation(地理位置)
DOM(元素)
Console (控制台)
Drag & Drop API(拖放)
Canvas(画布)
Fetch(网络通信)
History(浏览器会话)
但其实还有很多很多。不过要注意,并非所有 Web API 都可以广泛使用,可能在 Firefox 或 edge 里无法用。
这里有个经典的 Can I Use 网站,可以轻松查询某个 API 能否被某个浏览器使用。
比如 canvas:
第一个 全屏(Fullscreen API)
我们可能经常在视频网站使用,但是我们有可能直接不记得有这个经历。
导致我们很少关注。
但是,浏览器 里的全屏,并不是我们想象中,直接单纯的把浏览器上面的地址栏去掉,全屏了,而是可以针对不同的元素(以及其子元素)也全屏了。
不仅如此,还有在切换全屏、非全屏状态时也执行一些操作。
下面是一个演示,可以在我自制的 https://www.ccgxk.com/cellhtmleditor.html 简易 html 编辑器里尝试。
<div style="background:#eee; height:50px">普通背景区域(全屏后我会消失)</div>
<div id="target" style="background:#b3e5fc; padding:20px;">
要全屏的核心区域 <button onclick="tog()">进入/退出全屏</button>
</div>
<script>
const el = document.getElementById('target');
// 触发全屏逻辑
const tog = () => document.fullscreenElement ? document.exitFullscreen() : el.requestFullscreen();
// 状态切换时,在控制台 console
el.onfullscreenchange = () => {
const isFull = !!document.fullscreenElement;
console.log(isFull ? "动作:已进入专注模式(业务逻辑启动)" : "动作:已切回普通模式");
};
</script>
效果如下:
第二个 剪切板 (Clipboard Async API)
剪切板,就不用多介绍了吧。
其实剪切板的真实意思是,操作系统提供的缓冲区,让数据在应用程序内部和之间进行短期存储和传输,主要有三种操作:复制、剪切和粘贴。
我们平时可能多使用【点我复制】这种,这个是复制。但是其实还可以访问粘贴,只不过这个粘贴需要用户授权,否则很可怕,万一你剪切板里有密码或其他敏感信息,就完蛋了。
<input id="ipt" value="在此输入内容进行测试" style="width:200px">
<button onclick="handle('copy')">复制</button>
<button onclick="handle('cut')">剪切</button>
<button onclick="handle('paste')">粘贴</button>
<script>
const el = document.getElementById('ipt');
async function handle(type) {
console.log(`[系统日志] 用户触发了 ${type} 动作`); // 控制台日志
if (type === 'paste') {
el.value = await navigator.clipboard.readText(); // 粘贴
} else {
await navigator.clipboard.writeText(el.value); // 复制/剪切
if (type === 'cut') el.value = ''; // 清空源
}
}
</script>
效果如下:
三个按钮实现 复杂 剪切 粘贴 的演示。
第三个,监听元素变化(Resize Observer API)
这个就有点冷门,但是我们所有前端们都有想过,但压根连知道都不知道。
还是很实用的。
拖动右下角改变它的大小:
<div id="box" style="resize:both; overflow:auto; border:2px dashed #555; width:200px; padding:10px;">
</div>
<script>
const el = document.getElementById('box');
const observer = new ResizeObserver(entries => {
const { width, height } = entries[0].contentRect; // entries 是一个数组,包含所有被监听且发生变化的元素信息
el.textContent = `宽:${Math.round(width)} 高:${Math.round(height)}`; // 动作
});
observer.observe(el); // 开始监听
</script>
效果如下:
第四个,广播频道(Broadcast Channel API)
这个就有点硬核了!
如果你不知道这个 API,你肯定错过了很多潜在的创意!
因为在我们的直觉想法里,浏览器里一个个标签页,都是独立的王国,肯定不能相互通信,但其实是可以的。
不过注意,必须是 「same origin」,也就是同源,一个域名下才可以。
<input id="ipt" value="在另一个标签页看页面变化" style="width:200px">
<button onclick="send()">广播消息</button>
<div id="log" style="margin-top:8px;color:#555"></div>
<script>
const channel = new BroadcastChannel('app_sync');
const log = document.getElementById('log');
const send = () => {
channel.postMessage(ipt.value);
log.textContent = `已发送:${ipt.value}`;
};
channel.onmessage = (event) => {
log.textContent = `收到消息:${event.data}`;
};
</script>
演示如下:
在同源下,打开这个页面,然后输入信息后,广播信息,然后另一个标签页就收到了~ very cool!
第五个,性能(Performance Interface API)
一些内存、时间、navigation 等等指标很重要。
我写了一个简单的面板,帮助大家这样这个 api。
<h3>性能自检面板</h3>
<table border="1" cellpadding="5" cellspacing="0">
<thead>
<tr>
<th>属性名 (Key)</th>
<th>中文含义</th>
<th>当前值 (Value)</th>
</tr>
</thead>
<tbody id="data-body">
<tr><td colspan="3">数据加载中...</td></tr>
</tbody>
</table>
<script>
const dict = {
// NavigationTiming
name: "当前页面的 URL",
entryType: "条目类型(navigation)",
startTime: "开始时间(始终为 0)",
duration: "页面完全加载总耗时",
initiatorType: "发起类型",
nextHopProtocol: "使用的网络协议",
workerStart: "Service Worker 启动时间",
redirectStart: "重定向开始时间",
redirectEnd: "重定向结束时间",
fetchStart: "开始获取资源时间",
domainLookupStart: "DNS 查询开始时间",
domainLookupEnd: "DNS 查询结束时间",
connectStart: "TCP 连接开始时间",
secureConnectionStart: "TLS 握手开始时间",
connectEnd: "TCP 连接结束时间",
requestStart: "请求发送开始时间",
responseStart: "接收首字节时间(TTFB)",
responseEnd: "响应数据接收完成时间",
transferSize: "网络传输总字节数",
encodedBodySize: "压缩后资源大小",
decodedBodySize: "解压后资源大小",
serverTiming: "服务端性能指标",
unloadEventStart: "上一页面卸载开始时间",
unloadEventEnd: "上一页面卸载结束时间",
domInteractive: "DOM 可交互时间",
domContentLoadedEventStart: "DOMContentLoaded 开始时间",
domContentLoadedEventEnd: "DOMContentLoaded 结束时间",
domComplete: "DOM 完全加载时间",
loadEventStart: "load 事件开始时间",
loadEventEnd: "load 事件结束时间",
type: "导航类型",
redirectCount: "重定向次数",
activationStart: "预渲染激活时间",
// Memory
jsHeapSizeLimit: "JS 堆内存上限",
totalJSHeapSize: "当前已分配 JS 堆内存",
usedJSHeapSize: "当前使用中的 JS 堆内存",
// Timing
timeOrigin: "性能时间原点(页面创建时间)",
now: "当前高精度时间戳"
};
function format(key, val) {
if (typeof val === "number") {
if (key.toLowerCase().includes("size")) return val + " 字节";
return val.toFixed(2) + " 毫秒";
}
if (Array.isArray(val)) return val.length ? JSON.stringify(val) : "无";
return val;
}
function update() {
let html = "";
// Memory(仅 Chromium 可用)
if (performance.memory) {
for (let k in performance.memory) {
html += `<tr>
<td><code>${k}</code></td>
<td>${dict[k] || "内存相关指标"}</td>
<td><strong>${format(k, performance.memory[k])}</strong></td>
</tr>`;
}
}
// Timing 通用接口
html += `<tr>
<td><code>timeOrigin</code></td>
<td>${dict.timeOrigin}</td>
<td><strong>${performance.timeOrigin.toFixed(2)} 毫秒</strong></td>
</tr>`;
html += `<tr>
<td><code>now</code></td>
<td>${dict.now}</td>
<td><strong>${performance.now().toFixed(2)} 毫秒</strong></td>
</tr>`;
// Navigation Timing
const nav = performance.getEntriesByType("navigation")[0];
if (nav) {
const data = nav.toJSON();
for (let k in data) {
html += `<tr>
<td><code>${k}</code></td>
<td>${dict[k] || ""}</td>
<td><strong>${format(k, data[k])}</strong></td>
</tr>`;
}
}
document.getElementById("data-body").innerHTML = html;
}
update();
setInterval(update, 1000);
</script>
显示效果如下:
另外再插入 网络、电池信息。我就不新开标题了。
<h3>网络、电池信息</h3>
<table border="1" cellpadding="5">
<thead>
<tr><th>属性</th><th>中文含义</th><th>当前值</th></tr>
</thead>
<tbody id="data"></tbody>
</table>
<script>
const dict = {
// Network
effectiveType: "当前网络类型(slow-2g / 2g / 3g / 4g)",
downlink: "下行带宽估计值",
rtt: "网络往返延迟估计",
saveData: "是否开启省流量模式",
type: "物理连接类型(wifi / cellular 等)",
// Battery
charging: "是否正在充电",
chargingTime: "预计充满所需时间",
dischargingTime: "预计可用时间",
level: "当前电量比例"
};
const tbody = document.getElementById("data");
function row(k, v) {
return `<tr>
<td><code>${k}</code></td>
<td>${dict[k] || ""}</td>
<td><strong>${v}</strong></td>
</tr>`;
}
function renderNetwork() {
const n = navigator.connection;
if (!n) return "";
let html = "";
for (let k in n) {
if (typeof n[k] !== "function") {
html += row(k, typeof n[k] === "number" ? n[k] : String(n[k]));
}
}
return html;
}
async function renderBattery() {
if (!navigator.getBattery) return "";
const b = await navigator.getBattery();
return [
row("charging", b.charging),
row("chargingTime", b.chargingTime + " 秒"),
row("dischargingTime", b.dischargingTime + " 秒"),
row("level", Math.round(b.level * 100) + "%")
].join("");
}
async function update() {
tbody.innerHTML = renderNetwork() + await renderBattery();
}
update();
setInterval(update, 2000);
</script>
效果如下:
第六个,震动(Vibration API ,仅移动端可用)
这个是最好玩的,可惜只能在手机上体验。
没错,网页也可以振动,而是还可以自定义频率!
在我们的直觉里,好像震动只能使用原生的 APP ,但实际上网页也可以!
(大家可以使用移动端,打开这个网页体验: https://www.ccgxk.com/631.html )
<h3>(仅 移动端 有效,注意要关闭静音模式,才能体验!)</h3>
<button onclick="run(200)">短震 200ms</button>
<button onclick="run([500,110,500,110,450,110,200,110,170,40,450,110,200,110,170,40,500])">马里奥节奏</button>
<button onclick="run(0)">停止</button>
<div id="log" style="margin-top:20px; color:blue">点击按钮开始</div>
<script>
function run(p) {
//判断是否存在 API
if (!navigator.vibrate) return document.getElementById('log').innerText = "此设备不支持震动";
const success = navigator.vibrate(p); // 执行动作:p 为数字是单次震动,为数组是模式震动,为 0 是停止
document.getElementById('log').innerText = success ? (p === 0 ? "已停止" : "📳 正在震动...") : "调用失败(需用户点击触发)";
}
</script>
效果如下:
最后
当然,最后还有几个有意思的。大家有空可以捣鼓捣鼓、折腾折腾,未来这些都是创意的种子~
Payment Request API: 支付请求 API,为商家和用户提供一致的支付体验。
Touch Events: 触摸,提供相对底层的 API,可用于支持特定应用的多点触控交互,例如双指手势。
Page Visibility: 页面可见性,提供可监听的事件,用于判断文档何时变为可见或隐藏状态。
Channel Messaging API: 通道消息 API,在浏览上下文中传递消息的另一种优秀方式。但与广播机制不同,它专用于点对点消息传输
还有很多很多....