别急着装第三方库,这些事浏览器原生就能做到------Web Native API 实战指南
前端开发者的直觉反应往往是"找个 npm 包"。但现代浏览器已经内置了大量强大的原生 API:文件读写、系统分享、蓝牙通信、屏幕录制......本文盘点 12 个最实用的浏览器原生能力,每个都附带可运行代码和最新兼容性数据。
写在前面
每次遇到新需求,我们的肌肉反应是 npm install。但很多时候,浏览器早就内置了对应能力,只是你不知道。
随着 Chromium 内核一统天下,Safari 持续跟进,很多过去"实验性"的 API 如今已经有了可观的覆盖率。本文挑选了 12 个最实用的浏览器原生 API,按"成熟度"从高到低排列,每个都包含:
- 功能说明和使用场景
- 可直接复制的代码示例
- 📊 浏览器兼容性数据表
💡 兼容性图例说明
- ✅ 完整支持
- 🟡 部分支持 / 需要前缀 / 仅特定平台
- ❌ 不支持
- 数据统计自 Can I Use 全球浏览器份额(2026 年 6 月)
一、Intersection Observer API --- 懒加载与视口检测
这是什么
异步观察一个元素与其祖先元素或顶级文档视口的交叉状态。简单说:告诉你某个元素是否进入/离开了可视区域 。相比传统的 scroll + getBoundingClientRect 方案,它是浏览器原生优化过的,不会引起频繁重排。
真实代码
javascript
// 图片懒加载
const images = document.querySelectorAll('img[data-src]')
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target
img.src = img.dataset.src
img.removeAttribute('data-src')
observer.unobserve(img) // 加载一次后停止观察
}
})
}, {
root: null, // 相对于浏览器视口
rootMargin: '50px', // 提前 50px 触发
threshold: 0.1 // 10% 进入视口时触发
})
images.forEach((img) => observer.observe(img))
javascript
// 无限滚动
const sentinel = document.querySelector('#sentinel')
const scrollObserver = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
loadMoreData()
}
}, {
rootMargin: '200px' // 提前 200px 开始加载
})
scrollObserver.observe(sentinel)
📊 浏览器兼容性
| 浏览器 | 最低支持版本 | 状态 |
|---|---|---|
| Chrome | 51+ (2016) | ✅ |
| Edge | 15+ (2017) | ✅ |
| Firefox | 55+ (2017) | ✅ |
| Safari | 12.1+ (2019) | ✅ |
| iOS Safari | 12.2+ (2019) | ✅ |
| 全球覆盖率 | ~98.5% | 🟢 可放心使用 |
二、Clipboard API --- 剪贴板读写
这是什么
异步读写系统剪贴板,不仅支持文本,还支持图片等富文本内容。替代了已废弃的 document.execCommand('copy')。
真实代码
javascript
// 写入文本到剪贴板
async function copyText(text) {
try {
await navigator.clipboard.writeText(text)
console.log('复制成功')
} catch (err) {
console.error('复制失败:', err)
}
}
// 从剪贴板读取文本
async function pasteText() {
try {
const text = await navigator.clipboard.readText()
console.log('粘贴内容:', text)
} catch (err) {
console.error('读取失败:', err)
}
}
javascript
// 复制图片到剪贴板
async function copyImage(blob) {
try {
await navigator.clipboard.write([
new ClipboardItem({
'image/png': blob
})
])
console.log('图片已复制到剪贴板')
} catch (err) {
console.error('图片复制失败:', err)
}
}
// 从 Canvas 获取图片并复制
const canvas = document.querySelector('canvas')
canvas.toBlob(async (blob) => {
await copyImage(blob)
}, 'image/png')
📊 浏览器兼容性
| 浏览器 | writeText(写文本) | readText(读文本) | ClipboardItem(富文本) |
|---|---|---|---|
| Chrome | 66+ ✅ | 66+ ✅ | 76+ ✅ |
| Edge | 79+ ✅ | 79+ ✅ | 79+ ✅ |
| Firefox | 63+ ✅ | 63+ ✅ | 127+ ✅ |
| Safari | 13.1+ ✅ | 13.1+ 🟡(需用户手势) | 13.1+ ✅ |
| iOS Safari | 13.4+ ✅ | ❌ 不支持 | 13.4+ ✅ |
| 全球覆盖率 | ~96% | ~93% | ~88% |
⚠️ 安全要求 :Clipboard API 要求 HTTPS 环境(localhost 除外),且读取操作需要用户手势触发(如点击事件)。
三、Notification API --- 桌面通知
这是什么
在用户桌面上显示通知,即使网页不在前台也能收到。适用于消息提醒、任务完成通知等场景。
真实代码
javascript
// 请求通知权限
async function requestNotificationPermission() {
if (!('Notification' in window)) {
console.log('此浏览器不支持通知')
return
}
const permission = await Notification.requestPermission()
if (permission === 'granted') {
console.log('通知权限已开启')
}
}
// 发送通知
function showNotification(title, options = {}) {
const notification = new Notification(title, {
body: options.body || '',
icon: options.icon || '/icon.png',
badge: options.badge || '/badge.png',
tag: options.tag || '', // 相同 tag 会替换旧通知
requireInteraction: options.requireInteraction || false, // 不自动关闭
actions: [
{ action: 'reply', title: '回复' },
{ action: 'close', title: '忽略' }
]
})
notification.onclick = (event) => {
event.notification.close()
window.focus()
if (event.action === 'reply') {
handleReply()
}
}
// 5 秒后自动关闭
setTimeout(() => notification.close(), 5000)
}
// 使用示例
document.querySelector('#notify-btn').addEventListener('click', async () => {
await requestNotificationPermission()
showNotification('新消息', {
body: '张三:你好,今晚有空吗?',
tag: 'chat-message'
})
})
📊 浏览器兼容性
| 浏览器 | 最低支持版本 | 状态 |
|---|---|---|
| Chrome | 20+ (2012) | ✅ |
| Edge | 14+ (2016) | ✅ |
| Firefox | 22+ (2013) | ✅ |
| Safari | 7+ (2013, macOS) | ✅ |
| iOS Safari | 16.4+ (2023) | 🟡(仅 PWA) |
| 全球覆盖率 | ~97% | 🟢 可放心使用 |
💡 iOS 限制:iOS Safari 16.4+ 才开始支持 Web Notifications,且仅限于添加到主屏幕的 PWA 应用。
四、Geolocation API --- 地理位置定位
这是什么
获取用户的地理位置(经纬度)。这是最老牌的 Web API 之一,兼容性极好。
真实代码
javascript
// 获取当前位置(一次性)
function getCurrentPosition() {
if (!navigator.geolocation) {
console.log('此浏览器不支持地理定位')
return
}
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude, accuracy, altitude, speed } = position.coords
console.log(`纬度: ${latitude}, 经度: ${longitude}`)
console.log(`精度: ${accuracy} 米`)
console.log(`海拔: ${altitude} 米`)
console.log(`速度: ${speed} m/s`)
},
(error) => {
switch (error.code) {
case error.PERMISSION_DENIED:
console.log('用户拒绝了位置请求')
break
case error.POSITION_UNAVAILABLE:
console.log('位置信息不可用')
break
case error.TIMEOUT:
console.log('请求超时')
break
}
},
{
enableHighAccuracy: true, // 高精度模式
timeout: 10000, // 10 秒超时
maximumAge: 60000 // 缓存 1 分钟内的位置
}
)
}
// 持续监听位置变化(适用于导航场景)
const watchId = navigator.geolocation.watchPosition(
(position) => {
updateMap(position.coords)
},
(error) => console.error(error),
{ enableHighAccuracy: true }
)
// 停止监听
navigator.geolocation.clearWatch(watchId)
📊 浏览器兼容性
| 浏览器 | 最低支持版本 | 状态 |
|---|---|---|
| Chrome | 5+ (2010) | ✅ |
| Edge | 12+ (2015) | ✅ |
| Firefox | 3.5+ (2009) | ✅ |
| Safari | 5+ (2010) | ✅ |
| iOS Safari | 3.2+ (2010) | ✅ |
| 全球覆盖率 | ~97% | 🟢 可放心使用 |
⚠️ 安全要求:仅 HTTPS 环境可用,且必须获得用户授权。
五、Web Share API --- 系统原生分享
这是什么
调用操作系统的原生分享面板(移动端尤其好用),可以分享文本、链接甚至文件到微信、微博、邮件等任意目标应用。不用再自己实现分享按钮矩阵了。
真实代码
javascript
// 分享文本和链接
async function sharePage() {
if (!navigator.share) {
// 降级方案:复制链接到剪贴板
await navigator.clipboard.writeText(window.location.href)
alert('链接已复制,请手动分享')
return
}
try {
await navigator.share({
title: document.title,
text: '看看这篇好文章',
url: window.location.href
})
console.log('分享成功')
} catch (err) {
if (err.name !== 'AbortError') {
console.error('分享失败:', err)
}
}
}
// 分享文件(图片等)
async function shareFile(file) {
if (!navigator.canShare || !navigator.canShare({ files: [file] })) {
console.log('此浏览器不支持文件分享')
return
}
try {
await navigator.share({
files: [file],
title: '分享图片',
text: '看看这张图'
})
} catch (err) {
console.error('分享失败:', err)
}
}
// 绑定到按钮
document.querySelector('#share-btn').addEventListener('click', sharePage)
📊 浏览器兼容性
| 浏览器 | navigator.share | 文件分享 | 状态 |
|---|---|---|---|
| Chrome(Android) | 61+ ✅ | 76+ ✅ | ✅ |
| Chrome(桌面) | 89+ ✅ | 93+ ✅ | ✅ |
| Edge | 81+ ✅ | 93+ ✅ | ✅ |
| Safari(macOS) | 12.1+ ✅ | 14+ ✅ | ✅ |
| iOS Safari | 12.2+ ✅ | 14.5+ ✅ | ✅ |
| Firefox | ❌ 不支持 | ❌ 不支持 | ❌ |
| 全球覆盖率 | ~86% | ~80% | 🟡 建议做降级 |
💡 实用建议 :移动端覆盖率极高(iOS Safari + Chrome Android 占据大部分移动流量),桌面 Firefox 不支持。务必做好
navigator.share存在性检测和降级方案。
六、File System Access API --- 读写本地文件
这是什么
Web 应用可以直接读取、编辑和保存用户本地文件,像桌面应用一样工作。用户通过系统文件选择器授权访问,安全性有保障。
真实代码
javascript
// 打开文件并读取内容
async function openFile() {
try {
const [fileHandle] = await window.showOpenFilePicker({
types: [
{
description: '文本文件',
accept: { 'text/plain': ['.txt', '.md', '.json'] }
}
],
multiple: false
})
const file = await fileHandle.getFile()
const content = await file.text()
console.log('文件内容:', content)
return { fileHandle, content }
} catch (err) {
if (err.name !== 'AbortError') {
console.error('打开文件失败:', err)
}
}
}
// 保存文件(如果已有 fileHandle 则直接保存,否则弹出另存为)
async function saveFile(fileHandle, content) {
try {
// 如果没有 fileHandle,弹出"另存为"对话框
if (!fileHandle) {
fileHandle = await window.showSaveFilePicker({
suggestedName: 'untitled.txt',
types: [
{
description: '文本文件',
accept: { 'text/plain': ['.txt'] }
}
]
})
}
// 创建可写流
const writable = await fileHandle.createWritable()
await writable.write(content)
await writable.close()
console.log('文件保存成功')
return fileHandle
} catch (err) {
console.error('保存失败:', err)
}
}
// 使用示例
let currentFileHandle = null
document.querySelector('#open-btn').addEventListener('click', async () => {
const result = await openFile()
if (result) {
currentFileHandle = result.fileHandle
editor.value = result.content
}
})
document.querySelector('#save-btn').addEventListener('click', async () => {
await saveFile(currentFileHandle, editor.value)
})
📊 浏览器兼容性
| 浏览器 | showOpenFilePicker | showSaveFilePicker | 状态 |
|---|---|---|---|
| Chrome | 86+ ✅ | 86+ ✅ | ✅ |
| Edge | 86+ ✅ | 86+ ✅ | ✅ |
| Opera | 72+ ✅ | 72+ ✅ | ✅ |
| Firefox | ❌ 不支持 | ❌ 不支持 | ❌ |
| Safari | 🟡 16.4+ 部分(通过 Origin Private FS) | 🟡 16.4+ 部分 | 🟡 |
| 全球覆盖率 | ~73% | ~73% | 🟡 Chromium 系可用 |
⚠️ 限制说明:需要 HTTPS 环境。Firefox 目前不支持。Safari 的实现方式不同(基于 Origin Private File System),不提供系统级文件选择器。
七、Screen Capture API --- 屏幕录制
这是什么
捕获用户屏幕内容,可用于屏幕共享、录屏、远程协作等场景。配合 MediaRecorder 可以实现完整的屏幕录制功能。
真实代码
javascript
// 获取屏幕共享流
async function startScreenCapture() {
try {
const displayMedia = await navigator.mediaDevices.getDisplayMedia({
video: {
cursor: 'always', // 显示鼠标
displaySurface: 'browser' // 优先选择浏览器标签页
},
audio: true // 同时录制系统音频
})
// 创建 MediaRecorder 录制
const recorder = new MediaRecorder(displayMedia, {
mimeType: 'video/webm;codecs=vp9'
})
const chunks = []
recorder.ondataavailable = (e) => {
if (e.data.size > 0) chunks.push(e.data)
}
recorder.onstop = () => {
const blob = new Blob(chunks, { type: 'video/webm' })
const url = URL.createObjectURL(blob)
// 下载录制的视频
const a = document.createElement('a')
a.href = url
a.download = 'screen-recording.webm'
a.click()
URL.revokeObjectURL(url)
}
recorder.start()
// 用户点击"停止共享"时自动停止录制
displayMedia.getVideoTracks()[0].onended = () => {
recorder.stop()
}
return recorder
} catch (err) {
if (err.name !== 'NotAllowedError') {
console.error('屏幕捕获失败:', err)
}
}
}
document.querySelector('#record-btn').addEventListener('click', startScreenCapture)
📊 浏览器兼容性
| 浏览器 | getDisplayMedia | 状态 |
|---|---|---|
| Chrome | 72+ ✅ | ✅ |
| Edge | 79+ ✅ | ✅ |
| Firefox | 66+ 🟡(实现方式略有不同) | 🟡 |
| Safari | 13+ ✅ | ✅ |
| iOS Safari | 11+ 🟡(仅应用内捕获) | 🟡 |
| 全球覆盖率 | ~91% | 🟢 可放心使用 |
八、Web Bluetooth API --- 蓝牙设备通信
这是什么
Web 应用直接与低功耗蓝牙(BLE)设备通信,无需安装任何驱动或原生应用。适用于智能手环、传感器、IoT 设备等场景。
真实代码
javascript
// 连接蓝牙设备并读取电池电量
async function connectBluetoothDevice() {
try {
// 1. 请求设备(弹出蓝牙设备选择器)
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: ['battery_service'] }]
})
console.log('已选择设备:', device.name)
// 2. 连接 GATT 服务器
const server = await device.gatt.connect()
// 3. 获取服务
const service = await server.getPrimaryService('battery_service')
// 4. 获取特征值
const characteristic = await service.getCharacteristic('battery_level')
// 5. 读取数据
const value = await characteristic.readValue()
const batteryLevel = value.getUint8(0)
console.log(`电池电量: ${batteryLevel}%`)
// 6. 监听电量变化(实时)
await characteristic.startNotifications()
characteristic.addEventListener('characteristicvaluechanged', (event) => {
const level = event.target.value.getUint8(0)
console.log(`电量更新: ${level}%`)
})
// 断开连接监听
device.addEventListener('gattserverdisconnected', () => {
console.log('设备已断开')
})
} catch (err) {
console.error('蓝牙连接失败:', err)
}
}
document.querySelector('#bluetooth-btn').addEventListener('click', connectBluetoothDevice)
📊 浏览器兼容性
| 浏览器 | 最低支持版本 | 状态 |
|---|---|---|
| Chrome(Android/Mac/Windows) | 56+ ✅ | ✅ |
| Edge | 79+ ✅ | ✅ |
| Chrome(Linux) | 80+ ✅ | ✅ |
| Safari(macOS) | 🟡 不支持(截至2026) | ❌ |
| iOS Safari | 🟡 16.4+ 部分支持 | 🟡 |
| Firefox | ❌ 不支持 | ❌ |
| 全球覆盖率 | ~76% | 🟡 Chromium 系可用 |
⚠️ 限制:需要 HTTPS + 用户手势触发。Linux 上需要 BlueZ >= 5.43。iOS 支持有限,仅支持部分 GATT 操作。
九、Resize Observer API --- 元素尺寸监听
这是什么
监听元素尺寸变化(包括内容区、边框盒、滚动区)。比 window.resize 更强大,因为它可以监听任意元素的尺寸变化,不仅仅是 window。
真实代码
javascript
// 监听元素尺寸变化
const box = document.querySelector('.responsive-box')
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
const { width, height } = entry.contentRect
const borderBoxSize = entry.borderBoxSize?.[0]
console.log(`宽度: ${width}px, 高度: ${height}px`)
// 根据宽度切换布局
if (width < 600) {
entry.target.classList.add('mobile-layout')
entry.target.classList.remove('desktop-layout')
} else {
entry.target.classList.add('desktop-layout')
entry.target.classList.remove('mobile-layout')
}
}
})
resizeObserver.observe(box)
// 监听多个元素
const allCards = document.querySelectorAll('.card')
allCards.forEach((card) => resizeObserver.observe(card))
// 停止监听
// resizeObserver.unobserve(box)
// resizeObserver.disconnect()
📊 浏览器兼容性
| 浏览器 | 最低支持版本 | 状态 |
|---|---|---|
| Chrome | 64+ (2018) | ✅ |
| Edge | 79+ (2020) | ✅ |
| Firefox | 69+ (2019) | ✅ |
| Safari | 13.1+ (2020) | ✅ |
| iOS Safari | 13.4+ (2020) | ✅ |
| 全球覆盖率 | ~97% | 🟢 可放心使用 |
十、Vibration API --- 设备震动
这是什么
控制设备振动,提供触觉反馈。移动端游戏、通知提醒等场景的利器。API 非常简单,就一个方法。
真实代码
javascript
// 简单震动 200ms
navigator.vibrate(200)
// 震动模式:震200ms → 停100ms → 震200ms → 停100ms → 震500ms
navigator.vibrate([200, 100, 200, 100, 500])
// 模拟"错误"反馈
navigator.vibrate([100, 30, 100, 30, 100])
// 模拟"成功"反馈
navigator.vibrate([50, 20, 50])
// 停止震动(传入空数组或0)
navigator.vibrate(0)
navigator.vibrate([])
// 兼容性检测
function vibrate(pattern) {
if ('vibrate' in navigator) {
navigator.vibrate(pattern)
}
}
// 绑定到按钮点击
document.querySelectorAll('.btn').forEach((btn) => {
btn.addEventListener('click', () => vibrate(50))
})
📊 浏览器兼容性
| 浏览器 | 最低支持版本 | 状态 |
|---|---|---|
| Chrome(Android) | 32+ ✅ | ✅ |
| Firefox | 11+ ✅ | ✅ |
| Edge | 79+ ✅ | ✅ |
| Chrome(桌面) | ❌ 无硬件支持 | ❌ |
| Safari(macOS) | ❌ 不支持 | ❌ |
| iOS Safari | ❌ 不支持 | ❌ |
| 全球覆盖率 | ~82%(主要来自 Android) | 🟡 仅移动端有效 |
💡 注意:桌面浏览器虽然可能支持 API,但因为没有震动硬件,调用后不会有任何效果。此 API 主要面向 Android 设备。
十一、Web Storage API --- 本地存储
这是什么
包括 localStorage 和 sessionStorage,在浏览器中持久化存储键值对数据。这是最基础也最常用的原生能力之一。
真实代码
javascript
// localStorage --- 永久存储(除非手动清除)
// 存储
localStorage.setItem('username', '张三')
localStorage.setItem('preferences', JSON.stringify({
theme: 'dark',
fontSize: 16,
language: 'zh-CN'
}))
// 读取
const username = localStorage.getItem('username')
const prefs = JSON.parse(localStorage.getItem('preferences') || '{}')
// 删除
localStorage.removeItem('username')
// 清空所有
localStorage.clear()
// 监听跨标签页存储变化
window.addEventListener('storage', (e) => {
console.log(`键 ${e.key} 从 ${e.oldValue} 变为 ${e.newValue}`)
console.log('变化来源:', e.url)
})
// sessionStorage --- 仅当前会话有效(关闭标签页后清除)
sessionStorage.setItem('tempData', '临时数据')
const temp = sessionStorage.getItem('tempData')
javascript
// 封装带过期的 localStorage
const storage = {
set(key, value, ttl) {
const item = {
value: value,
expiry: ttl ? Date.now() + ttl : null
}
localStorage.setItem(key, JSON.stringify(item))
},
get(key) {
const raw = localStorage.getItem(key)
if (!raw) return null
const item = JSON.parse(raw)
if (item.expiry && Date.now() > item.expiry) {
localStorage.removeItem(key)
return null
}
return item.value
}
}
// 使用:存储 1 小时后过期
storage.set('token', 'abc123', 60 * 60 * 1000)
const token = storage.get('token')
📊 浏览器兼容性
| 浏览器 | localStorage | sessionStorage | 状态 |
|---|---|---|---|
| Chrome | 4+ ✅ | 5+ ✅ | ✅ |
| Edge | 12+ ✅ | 12+ ✅ | ✅ |
| Firefox | 3.5+ ✅ | 2+ ✅ | ✅ |
| Safari | 4+ ✅ | 4+ ✅ | ✅ |
| iOS Safari | 3.2+ ✅ | 3.2+ ✅ | ✅ |
| 全球覆盖率 | ~99% | ~99% | 🟢 可放心使用 |
十二、Broadcast Channel API --- 跨标签页通信
这是什么
允许同一个源下的不同浏览器上下文(如多个标签页、iframe、Worker)之间进行实时通信。比 storage 事件更直接、更高效。
真实代码
javascript
// 创建广播频道
const channel = new BroadcastChannel('app_updates')
// 发送消息(其他标签页会收到)
channel.postMessage({
type: 'user_logout',
data: { userId: 123 }
})
// 接收消息
channel.onmessage = (event) => {
const { type, data } = event.data
console.log(`收到广播: ${type}`, data)
switch (type) {
case 'user_logout':
// 在其他标签页也执行登出
window.location.href = '/login'
break
case 'theme_change':
document.body.className = data.theme
break
}
}
// 关闭频道
channel.close()
javascript
// 实战场景:多标签页同步登录状态
// 登录成功后广播通知其他标签页
async function login(credentials) {
const result = await api.login(credentials)
localStorage.setItem('token', result.token)
// 广播登录成功
const channel = new BroadcastChannel('auth')
channel.postMessage({ type: 'login', user: result.user })
channel.close()
}
// 每个页面的全局监听
const authChannel = new BroadcastChannel('auth')
authChannel.onmessage = (event) => {
if (event.data.type === 'login') {
// 刷新当前页面以加载用户状态
location.reload()
} else if (event.data.type === 'logout') {
localStorage.removeItem('token')
location.href = '/login'
}
}
📊 浏览器兼容性
| 浏览器 | 最低支持版本 | 状态 |
|---|---|---|
| Chrome | 54+ (2016) | ✅ |
| Edge | 79+ (2020) | ✅ |
| Firefox | 38+ (2015) | ✅ |
| Safari | 15.4+ (2022) | ✅ |
| iOS Safari | 15.4+ (2022) | ✅ |
| 全球覆盖率 | ~96% | 🟢 可放心使用 |
📊 12 大原生 API 兼容性总览
为了方便快速查阅,这里汇总所有 API 的兼容性数据:
| API | Chrome | Edge | Firefox | Safari | iOS Safari | 全球覆盖率 | 推荐程度 |
|---|---|---|---|---|---|---|---|
| Intersection Observer | 51+ ✅ | 15+ ✅ | 55+ ✅ | 12.1+ ✅ | 12.2+ ✅ | ~98.5% | 🟢 放心用 |
| Clipboard API | 66+ ✅ | 79+ ✅ | 63+ ✅ | 13.1+ ✅ | 13.4+ ✅ | ~96% | 🟢 放心用 |
| Notification API | 20+ ✅ | 14+ ✅ | 22+ ✅ | 7+ ✅ | 16.4+ 🟡 | ~97% | 🟢 放心用 |
| Geolocation API | 5+ ✅ | 12+ ✅ | 3.5+ ✅ | 5+ ✅ | 3.2+ ✅ | ~97% | 🟢 放心用 |
| Web Share API | 61+ ✅ | 81+ ✅ | ❌ | 12.1+ ✅ | 12.2+ ✅ | ~86% | 🟡 需降级 |
| File System Access | 86+ ✅ | 86+ ✅ | ❌ | 16.4+ 🟡 | ❌ | ~73% | 🟡 需检测 |
| Screen Capture | 72+ ✅ | 79+ ✅ | 66+ 🟡 | 13+ ✅ | 11+ 🟡 | ~91% | 🟢 放心用 |
| Web Bluetooth | 56+ ✅ | 79+ ✅ | ❌ | ❌ | 16.4+ 🟡 | ~76% | 🟡 需检测 |
| Resize Observer | 64+ ✅ | 79+ ✅ | 69+ ✅ | 13.1+ ✅ | 13.4+ ✅ | ~97% | 🟢 放心用 |
| Vibration API | 32+ ✅ | 79+ ✅ | 11+ ✅ | ❌ | ❌ | ~82% | 🟡 仅移动端 |
| Web Storage | 4+ ✅ | 12+ ✅ | 3.5+ ✅ | 4+ ✅ | 3.2+ ✅ | ~99% | 🟢 放心用 |
| Broadcast Channel | 54+ ✅ | 79+ ✅ | 38+ ✅ | 15.4+ ✅ | 15.4+ ✅ | ~96% | 🟢 放心用 |
📌 数据说明:以上兼容性数据基于 Can I Use 和 MDN Web Docs,统计时间为 2026 年 6 月。全球覆盖率参考 StatCounter 全球浏览器市场份额加权计算。"🟡" 表示部分支持或需要降级方案。
实战建议
1. 始终做特性检测
javascript
// 通用特性检测模式
if ('share' in navigator) {
// 使用原生 Web Share
} else {
// 降级到自定义分享面板或复制链接
}
2. HTTPS 是前提
大多数现代 API(Clipboard、Geolocation、Bluetooth、File System Access 等)都要求 HTTPS 环境 。本地开发时 localhost 和 127.0.0.1 被视为安全上下文,可以直接使用。
3. 用户手势触发
涉及隐私和安全的 API(剪贴板读取、蓝牙连接、文件选择、屏幕共享)必须由用户手势触发(如 click 事件回调中调用),不能在页面加载时自动调用。
4. 优雅降级策略
javascript
// 分层降级示例:复制功能
async function copyToClipboard(text) {
// 第一选择:现代 Clipboard API
if (navigator.clipboard?.writeText) {
try {
await navigator.clipboard.writeText(text)
showToast('已复制')
return
} catch {}
}
// 第二选择:execCommand(已废弃但仍可用)
const textarea = document.createElement('textarea')
textarea.value = text
textarea.style.position = 'fixed'
textarea.style.opacity = '0'
document.body.appendChild(textarea)
textarea.select()
document.execCommand('copy')
document.body.removeChild(textarea)
showToast('已复制')
}
总结
浏览器原生能力已经远超大多数开发者的认知。从文件系统到蓝牙通信,从屏幕录制到跨标签页广播,很多过去需要第三方库甚至原生应用才能实现的功能,现在一行 JavaScript 就能搞定。
选用原则很简单:
- 覆盖率 > 95% 的 API(Intersection Observer、Clipboard、Notification、Geolocation、Resize Observer、Web Storage、Broadcast Channel)------ 直接用,不用犹豫
- 覆盖率 80%-95% 的 API(Web Share、Screen Capture、Vibration)------ 用,但做好降级
- 覆盖率 < 80% 的 API(File System Access、Web Bluetooth)------ 做好特性检测,面向特定场景使用
下次遇到需求时,先查查 Can I Use 和 MDN Web Docs,也许浏览器原生就能搞定,不用再 npm install 了。
参考资料:
- Can I Use --- 浏览器兼容性查询
- MDN Web Docs --- Web API 官方文档
- web.dev --- Google Web Capabilities 指南
如果这篇文章对你有帮助,欢迎点赞收藏。你在项目中用过哪些浏览器原生 API?欢迎在评论区分享你的实践经验。