你是否也遇到过这些场景:
- 页面快关了,埋点请求总被浏览器"砍单";
- 无限滚动一滑就卡,getBoundingClientRect 算到怀疑人生;
- 产品要"3 小时前"文案,却给了一坨时间戳;
- 多 Tab 之间状态不同步,用户疯狂吐槽;
......
其实,浏览器早已把解决方案打包好,只是它们藏在文档角落,名字还"劝退"。今天,我们就来揭开 15 个"冷门却逆天"的原生 API,让你少写轮子、多睡午觉。
1. Navigator.sendBeacon------临终埋点"必达快递"
痛点 :在 beforeunload
里发 Ajax,浏览器直接取消请求,数据丢失。
解药 :sendBeacon 专为"页面垂死"设计,异步、非阻塞、即使关闭 Tab 也能送达。
js
window.addEventListener('pagehide', () => {
navigator.sendBeacon('/api/log', JSON.stringify({
stayTime: Date.now() - enterTime,
uid: getUid()
}));
});
注意:
- 只支持 POST,且数据量≤64 KB(各浏览器略有差异)。
- 无法读取响应,适用于"发完即走"的日志、统计场景。
2. Intl 全家桶------国际化一条龙,0 依赖
API | 一行代码搞定 |
---|---|
Intl.RelativeTimeFormat |
new Intl.RelativeTimeFormat('zh').format(-3, 'hour') → "3 小时前" |
Intl.NumberFormat |
new Intl.NumberFormat('de', {style:'currency', currency:'EUR'}).format(1234.5) → "1.234,50 €" |
Intl.Collator |
数组.sort(new Intl.Collator('sv').compare) 按瑞典语字母序 |
为什么冷门?
名字像"后端专属",很多人硬写 if/else
拼字符串。
3. IntersectionObserver------scroll 事件性能杀手终结者
原理 :浏览器告诉你"元素进/出视口",无需自己算坐标。
场景:懒加载、无限滚动、曝光埋点、动画触发。
js
const io = new IntersectionObserver((entries) => {
entries.forEach(e => {
if (e.isIntersecting) {
loadImg(e.target); // 加载真实图片
io.unobserve(e.target); // 加载完取消监听
}
});
}, { rootMargin: '100px' }); // 提前 100px 预加载
document.querySelectorAll('img[data-src]').forEach(img => io.observe(img));
性能对比 :
scroll 监听→每秒触发 60 次;IntersectionObserver→仅交叉时触发 1 次,内存占用下降 90%。
4. TreeWalker------百万节点遍历"内存刺客"
当你只要"文本节点"或"跳过隐藏节点"时,比 querySelectorAll('*')
省 N 倍内存。
js
const walker = document.createTreeWalker(
root,
NodeFilter.SHOW_TEXT,
{ acceptNode: node => /hello/i.test(node.data) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT }
);
const result = [];
while (walker.nextNode()) result.push(walker.currentNode);
5. Element.checkVisibility()------真正"看得见"才干活
一次性排除 display:none
、visibility:hidden
、opacity:0
、被祖先裁剪等所有情况。
js
if (ad.checkVisibility()) fireExposure(); // 广告可见曝光
6. scrollIntoViewIfNeeded(true)------"智能滚动"不扰民
只有当元素完全不在视口时才滚动,避免"用户已看一半你还硬滚"。
js
elem.scrollIntoViewIfNeeded?.(true) || elem.scrollIntoView({block:'nearest'});
7. getComputedStyle(elem, '::before')------伪元素样式也能读
主题切换测试、组件库快照必备。
js
window.getComputedStyle(btn, '::before').content; // "→"
8. requestIdleCallback------等浏览器"有空"再打工
把非关键任务拆成碎片,不阻塞帧渲染。
js
requestIdleCallback(deadline => {
while (deadline.timeRemaining() > 0 && taskQueue.length) {
runOne(taskQueue.shift());
}
if (taskQueue.length) requestIdleCallback(arguments.callee);
});
9. PerformanceObserver------线上性能"显微镜"
精度微秒级 ,比 Date.now()
靠谱 1000 倍。
js
new PerformanceObserver(list => {
for (const e of list.getEntries()) console.log(e.name, e.duration);
}).observe({type: 'measure', buffered: true});
performance.mark('A');
await fetch('/api');
performance.mark('B');
performance.measure('fetch', 'A', 'B');
10. BroadcastChannel------同源多 Tab 实时"群聊"
登录态、主题色、购物车一键同步。
js
const bc = new BroadcastChannel('app');
bc.onmessage = e => {
if (e.data.cmd === 'logout') location.reload();
};
bc.postMessage({cmd: 'theme', value: 'dark'});
11. Web Share API------原生分享面板一键呼出
iOS/Android/桌面端 都能调起系统级分享,无需混装 SDK。
js
navigator.share?.({
title: '我在用的小工具',
text: '推荐给你',
url: location.href
}).catch(() => {});
12. Page Visibility + sendBeacon 组合------100% 送达的停留时长
利用 visibilitychange
代替 beforeunload
,移动端更可靠。
js
let t = Date.now();
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
navigator.sendBeacon('/api/duration', JSON.stringify({duration: Date.now() - t}));
}
});
13. DOM"三剑客"
方法 | 一句话记忆 |
---|---|
insertAdjacentHTML('afterbegin', html) |
不破坏事件代理,极速插入同级节点 |
range.surroundContents(wrapper) |
选区一键加高亮,富文本编辑器神器 |
node.isEqualNode(other) |
深度比较两棵 DOM 树,单元测试/虚拟 DOM 必备 |
14. Web Audio + AnalyserNode------"音频可视化"免库
上传语音预览时,实时绘制频谱条,无需引入第三方图表。
15. CSS Houdini & Paint Worklet------让 JS 直接画 CSS 背景
动态波浪边框、二维码背景、复杂渐变,GPU 加速、可跟随 CSS 变量实时刷新。
js
CSS.paintWorklet.addModule('ripple.js');
css
.box {
--ripple-color: #673ab7;
background-image: paint(ripple);
}
结语:把"隐藏神技"用起来
- 先挑 3 个立刻见效 :
sendBeacon
解决埋点丢失 →IntersectionObserver
干掉滚动卡顿 →Intl.*
少写 200 行格式化代码。 - 再按业务场景补位 :
富文本 →TreeWalker
+Range
;性能优化 →requestIdleCallback
+PerformanceObserver
;多 Tab 同步 →BroadcastChannel
。
浏览器进化速度远超我们学 API 的速度,把原生能力吃透,就是最大的"提效" 。
如果本文有帮到你,点个赞、收个藏,也欢迎在评论区补充你的"私藏冷门 API"。Happy Coding!