浏览器 API 你可能不知道的实用功能
Web API 越来越丰富,有些 API 虽然不常被提及,但在实际开发中能省不少事。这篇文章整理了一些 2025 年已经可以放心使用的浏览器 API。
Clipboard API
复制到剪贴板终于不需要 Flash 或 execCommand 了:
// 复制文本
await navigator.clipboard.writeText('Hello World');
// 读取剪贴板
const text = await navigator.clipboard.readText();
// 复制富文本(HTML)
await navigator.clipboard.write([
new ClipboardItem({
'text/html': new Blob(['<b>Bold</b> text'], { type: 'text/html' }),
'text/plain': new Blob(['Bold text'], { type: 'text/plain' }),
}),
]);
注意:需要在用户交互(点击、按键)的回调里调用,否则浏览器会拒绝。
Intersection Observer
检测元素是否进入视口,替代 scroll 事件监听:
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
console.log('元素进入视口', entry.target);
observer.unobserve(entry.target); // 只触发一次
}
});
},
{ threshold: 0.1 } // 10% 可见时触发
);
observer.observe(document.querySelector('.lazy-image'));
典型用途:懒加载图片、无限滚动、曝光统计。
ResizeObserver
监听元素尺寸变化(不是窗口尺寸):
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
const { width, height } = entry.contentRect;
console.log(`元素尺寸: ${width}x${height}`);
}
});
resizeObserver.observe(document.querySelector('.container'));
比 window.resize 精确——可以监听任意 DOM 元素的尺寸变化,不只是窗口。
Performance Observer
监听长任务(Long Tasks),超过 50ms 的任务会阻塞主线程:
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(`长任务: ${entry.duration}ms`, entry.name);
}
});
observer.observe({ entryTypes: ['longtask'] });
这个 API 对于排查页面卡顿很有用。如果发现频繁出现长任务,就需要考虑拆分计算、使用 Web Worker 或 requestIdleCallback。
structuredClone
深拷贝对象,替代 JSON.parse(JSON.stringify()):
const original = {
date: new Date(),
regex: /test/g,
map: new Map([['key', 'value']]),
set: new Set([1, 2, 3]),
nested: { arr: [1, 2, 3] },
};
const cloned = structuredClone(original);
// JSON.parse(JSON.stringify()) 丢失 Date、RegExp、Map、Set
// structuredClone 完整保留
structuredClone 能正确处理 Date、RegExp、Map、Set、ArrayBuffer、Blob 等类型。缺点是不能克隆函数和 DOM 节点。
AbortController
取消网络请求和任何可取消的异步操作:
const controller = new AbortController();
// 取消 fetch 请求
fetch('/api/data', { signal: controller.signal });
// 取消 EventSource
const es = new EventSource('/api/stream');
es.addEventListener('message', handler);
// 关闭时
es.close();
// 5 秒后取消
setTimeout(() => controller.abort(), 5000);
在 React 里用 AbortController 清理副作用:
useEffect(() => {
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then(res => res.json())
.then(setData);
return () => controller.abort();
}, []);
URL Pattern API
匹配 URL 路径,比正则表达式更直观:
const pattern = new URLPattern('/posts/:id', 'https://example.com');
pattern.test('https://example.com/posts/123'); // true
pattern.exec('https://example.com/posts/123');
// { id: '123', ... }
在 Service Worker 里用这个 API 做路由匹配很方便。
View Transitions API
页面切换动画,原生 API:
// 触发页面过渡动画
document.startViewTransition(() => {
// 更新 DOM
updateContent();
});
浏览器会自动在新旧页面之间做动画(淡入淡出)。可以配合 CSS 自定义动画效果:
::view-transition-old(root) {
animation: fade-out 0.2s ease-out;
}
::view-transition-new(root) {
animation: fade-in 0.2s ease-in;
}
SPA 路由切换时加这个,体验提升很大。
File System Access API
读写本地文件,可以做一个简单的"打开文件"和"保存文件"功能:
// 打开文件
const [fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const content = await file.text();
// 保存文件
const fileHandle = await window.showSaveFilePicker({
suggestedName: 'document.txt',
});
const writable = await fileHandle.createWritable();
await writable.write('Hello World');
await writable.close();
浏览器安全限制比较多(需要 HTTPS、用户手势触发),但功能确实强大。可以用来做在线编辑器的本地文件支持。
注意兼容性
这些 API 在 Chrome 里的支持都很好,Safari 和 Firefox 对部分 API 支持较晚:
| API | Chrome | Safari | Firefox |
|---|---|---|---|
| Clipboard | 66+ | 13.1+ | 63+ |
| IntersectionObserver | 51+ | 12.1+ | 55+ |
| ResizeObserver | 64+ | 13.1+ | 69+ |
| structuredClone | 98+ | 15.4+ | 94+ |
| View Transitions | 111+ | 18+ | 未支持 |
| File System | 86+ | 15.2+ | 未支持 |
用之前查一下 caniuse,对不支持的浏览器做好降级处理。
这些 API 都是浏览器原生提供的,不需要任何第三方库。掌握了它们,很多以前需要依赖库才能实现的功能现在几行代码就能搞定。