20个浏览器原生API帮你干掉一堆npm依赖

更新日期: 2026-09-20 阅读: 86 标签: npm

做前端项目,遇到需求第一反应经常是打开终端敲 npm install。复制文本装个库,弹窗装个库,懒加载装个库,深拷贝再装一个。

其实这些年浏览器已经内置了不少能力,很多小需求根本不需要额外装东西。这篇文章按项目里常见的场景,整理20个可以直接上手的原生API。每个都给一段最小代码,挑你最常用的那几个先试起来。


一、用户交互类

1. Clipboard API:复制文本不用 clipboard.js

做复制链接、邀请码、命令的场景很多,以前要装库,现在直接用 navigator.clipboard:

async function copyText(text) {
  await navigator.clipboard.writeText(text);
  console.log('copied');
}

copyText('npm create vite@latest');

两个前提要注意:页面得跑在 HTTPS 或 localhost 上,而且通常要用户点击才能触发。写按钮事件最稳:

button.addEventListener('click', async () => {
  await navigator.clipboard.writeText(location.href);
});

这个 API 从 2020 年 3 月起在所有浏览器中可用,现在基本不用操心兼容问题。

2. Web Share API:调起系统分享面板

很多 H5 页面只是想拉起系统的分享功能,没必要接一堆第三方 SDK:

async function sharePage() {
  if (!navigator.share) return;
  await navigator.share({
    title: document.title,
    text: '这篇文章不错',
    url: location.href,
  });
}

桌面端和部分浏览器不一定支持,按钮可以按能力隐藏:

shareButton.hidden = !navigator.share;


二、弹层与对话框

3. Popover API:轻量弹层不用自己管层级

菜单、气泡卡片、更多操作面板,可以先看看 popover:

<button popovertarget="menu">更多</button>

<div id="menu" popover>
  <button>编辑</button>
  <button>删除</button>
</div>

它会自动处理显示、隐藏和顶层展示,不用再手写 z-index: 9999。Popover API 自 2025 年 1 月起在所有现代浏览器中可用。

有一点要区分清楚:Popover API 创建的是非模态弹层,显示时页面其他部分仍可交互。如果你需要模态弹窗(背景不可操作),应该用下面的 <dialog> 元素。

4. Dialog:确认框和表单弹窗的正经解法

如果你还在用 div 模拟模态框,<dialog> 可以帮你省掉大量焦点管理代码:

<dialog id="confirmDialog">
  <p>确认删除这条记录吗?</p>
  <button value="cancel">取消</button>
  <button value="ok">删除</button>
</dialog>
const dialog = document.querySelector('#confirmDialog');

deleteButton.addEventListener('click', () => {
  dialog.showModal();
});

dialog.addEventListener('click', (event) => {
  if (event.target.value === 'ok') {
    console.log('delete');
  }
  dialog.close();
});

showModal() 会自动处理焦点、ESC 关闭、背景遮罩这些细节。


三、滚动与尺寸监听

5. IntersectionObserver:懒加载和曝光埋点

用 scroll 事件做懒加载容易写出性能问题。元素进出视口,优先用 IntersectionObserver:

const observer = new IntersectionObserver((entries) => {
  for (const entry of entries) {
    if (!entry.isIntersecting) continue;
    const img = entry.target;
    img.src = img.dataset.src;
    observer.unobserve(img);
  }
});

document.querySelectorAll('img[>).forEach((img) => {
  observer.observe(img);
});

曝光埋点也是同一个思路:元素第一次进入视口时上报,然后 unobserve。

6. ResizeObserver:监听元素尺寸,不盯着 window

响应式组件里经常需要知道容器宽度,而不是窗口宽度:

const box = document.querySelector('.chart');

const observer = new ResizeObserver(([entry]) => {
  const width = entry.contentRect.width;
  box.dataset.size = width > 600 ? 'wide' : 'narrow';
});

observer.observe(box);

图表、虚拟列表、卡片布局都能用它。卸载组件时记得 observer.disconnect()。


四、通信与同步

7. BroadcastChannel:多标签页通信

一个标签页退出登录,其他标签页也要同步退出,不用轮询 localStorage:

const channel = new BroadcastChannel('auth');

logoutButton.addEventListener('click', () => {
  channel.postMessage({ type: 'logout' });
});

channel.addEventListener('message', (event) => {
  if (event.data.type === 'logout') {
    location.href = '/login';
  }
});

同源页面都能收到消息。后台管理系统、多标签工作台很常用。

8. Web Locks:避免多标签重复执行任务

有些任务只应该跑一次,比如刷新 token、同步离线队列:

async function syncOnce() {
  if (!navigator.locks) return;
  await navigator.locks.request('sync-queue', async () => {
    console.log('only one tab runs this');
    await sendPendingRequests();
  });
}

它的核心价值是解决“用户开了 5 个标签页,5 个页面同时干同一件事”的问题。Web Locks API 自 2022 年 3 月起已在各浏览器中可用。

9. StorageEvent:localStorage 跨标签同步

如果只是同步一个简单状态,storage 事件够用了:

window.addEventListener('storage', (event) => {
  if (event.key === 'theme') {
    document.documentElement.dataset.theme = event.newValue;
  }
});

function setTheme(theme) {
  localStorage.setItem('theme', theme);
  document.documentElement.dataset.theme = theme;
}

注意一点:修改 localStorage 的当前页面不会收到自己的 storage 事件,所以本页状态要自己更新。


五、文件处理

10. URL.createObjectURL:更轻的文件预览

预览图片、视频、PDF 时,createObjectURL 比 FileReader 更直接,性能也更好:

fileInput.addEventListener('change', () => {
  const file = fileInput.files[0];
  if (!file) return;

  const url = URL.createObjectURL(file);
  preview.src = url;

  preview.onload = () => {
    URL.revokeObjectURL(url);
  };
});

关键点是用完释放,别让对象 URL 一直挂着。大文件预览优先用这个,别一股脑读成 base64 字符串。

11. structuredClone:深拷贝别再 JSON 转一圈

JSON.parse(JSON.stringify(obj)) 会丢 Date、Map、Set、undefined,还处理不了循环引用:

const source = {
  createdAt: new Date(),
  tags: new Set(['browser', 'api']),
};

const copy = structuredClone(source);
console.log(copy.createdAt instanceof Date); // true
console.log(copy.tags instanceof Set);       // true

这个 API 自 2022 年 3 月起可在最新设备和浏览器上运行,普通业务对象深拷贝优先试试它。


六、动效

12. Web Animations API:简单动效不用动画库

按钮反馈、列表进入、提示条消失,这类动效直接用 element.animate():

toast.animate(
  [
    { opacity: 0, transform: 'translateY(8px)' },
    { opacity: 1, transform: 'translateY(0)' },
  ],
  {
    duration: 180,
    easing: 'ease-out',
    fill: 'both',
  }
);

它返回的是 Animation 对象,可以暂停、反放、等待结束:

const animation = panel.animate(keyframes, options);
await animation.finished;
panel.remove();

13. View Transitions API:页面状态切换更顺

列表切详情、主题切换、局部视图切换,很多时候不需要上复杂动画方案:

function switchTheme(theme) {
  const update = () => {
    document.documentElement.dataset.theme = theme;
  };

  if (!document.startViewTransition) {
    update();
    return;
  }

  document.startViewTransition(update);
}

再配一点 CSS:

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 220ms;
}

这个 API 的浏览器支持在过去一年进步很大。单文档 View Transitions 目前 Chrome/Edge 111+、Safari 18+、Firefox 144+ 都已支持。适合做体验增强,不要把核心功能绑死在它上面。


七、其他常用能力

14. PerformanceObserver:采样页面性能

想看 LCP、资源加载、长任务,不用马上接监控 SDK:

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log(entry.entryType, entry.name, entry.startTime);
  }
});

observer.observe({
  entryTypes: ['largest-contentful-paint', 'resource', 'longtask'],
});

15. online/offline:离线提示不用猜

function updateNetworkStatus() {
  document.body.dataset.online = String(navigator.onLine);
}

window.addEventListener('online', updateNetworkStatus);
window.addEventListener('offline', updateNetworkStatus);
updateNetworkStatus();

navigator.onLine 不是万能网络诊断,只能做轻量提示。真正的请求仍然要处理失败和重试。

16. CompressionStream:浏览器里压缩数据

要把日志、配置压成 gzip,不一定非得引入压缩库:

async function gzipText(text) {
  const stream = new Blob([text])
    .stream()
    .pipeThrough(new CompressionStream('gzip'));
  return await new Response(stream).blob();
}

const file = await gzipText(JSON.stringify({ hello: 'browser' }));
console.log(file.size);

这个 API 对 Chromium 系浏览器支持较好,上线前先看你的用户浏览器分布。

17. File System Access API:直接读写本地文件

做 Markdown 编辑器、图片处理工具时,它能让 Web 应用更像桌面软件:

async function openTextFile() {
  const [handle] = await window.showOpenFilePicker({
    types: [
      {
        description: 'Text',
        accept: { 'text/plain': ['.txt', '.md'] },
      },
    ],
  });

  const file = await handle.getFile();
  return await file.text();
}

保存文件:

async function saveText(text) {
  const handle = await window.showSaveFilePicker({
    suggestedName: 'note.md',
  });

  const writable = await handle.createWritable();
  await writable.write(text);
  await writable.close();
}

注意这个 API 的兼容性限制很大。目前只有 Chromium 系浏览器(Chrome 105+、Edge 105+)在 Windows、macOS、ChromeOS、Linux 和 Android 上支持,Safari 和 Firefox 完全不支持。适合工具型产品做渐进增强,不能作为核心依赖。

18. EyeDropper:浏览器里直接取色

做低代码、设计工具、主题配置时很好用:

async function pickColor() {
  if (!('EyeDropper' in window)) return;
  const eyeDropper = new EyeDropper();
  const result = await eyeDropper.open();
  console.log(result.sRGBHex);
}

兼容性不算完整,适合做增强能力:支持就展示取色按钮,不支持就让用户手动输入色值。

19. MutationObserver:监听 DOM 变化

接入第三方脚本、富文本编辑器时,DOM 变化不一定经过你的框架状态:

const target = document.querySelector('#editor');

const observer = new MutationObserver((mutations) => {
  console.log('changed', mutations.length);
});

observer.observe(target, {
  childList: true,
  subtree: true,
  characterData: true,
});

别拿它替代 React/Vue 状态管理。它更适合处理“外部代码改了 DOM,我需要知道”的场景。

20. FileReader:本地文件预览

头像上传前预览、导入 JSON 配置:

fileInput.addEventListener('change', () => {
  const file = fileInput.files[0];
  if (!file) return;

  const reader = new FileReader();
  reader.onload = () => {
    preview.src = reader.result;
  };
  reader.readAsDataURL(file);
});

大文件不建议一股脑读成字符串,要考虑流式处理或分片。如果是图片预览,用上面的 URL.createObjectURL 更合适。


速查表

场景原生能力
复制文本Clipboard API
系统分享Web Share API
弹出菜单Popover API
模态确认框Dialog
页面取色EyeDropper
懒加载 / 曝光IntersectionObserver
容器尺寸变化ResizeObserver
DOM 外部变化MutationObserver
性能采样PerformanceObserver
多标签通信BroadcastChannel
多标签互斥任务Web Locks
离线提示online / offline
localStorage 同步StorageEvent
文件读取FileReader
文件预览URL.createObjectURL
深拷贝structuredClone
gzip 压缩CompressionStream
本地文件读写File System Access API
基础动效Web Animations API
页面切换动效View Transitions API

什么时候该用,什么时候不该用

不是说所有库都不该装。日期处理、复杂拖拽、富文本编辑器、虚拟列表、图表这些领域,成熟库依然更省心,自己写反而容易踩坑。

但边界清晰的小需求,先查一下浏览器有没有原生能力,往往能少引一个依赖、少维护一层封装,也少一份供应链风险。对前端项目来说,包体积只是表面上的收益,真正省下来的是长期维护成本。

你项目里最想用原生 API 替代掉哪个 npm 包?

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

相关推荐

npm run build根据不同参数打包不同环境url

这篇文章主要介绍了vue项目中Npm run build 根据环境传递参数方法来打包不同域名,使用npm run build --xxx,根据传递参数xxx来判定不同的环境,给出不同的域名配置,具体内容详情大家参考下:config文件夹下dev.env.js中修改代码、prod.env.js中修改代码 HOST为截取到的参数

npm安装模块时报错:no such file or directory

使用node.js和npm,在安装模块的时候报错npm WARN saveError ENOENT: no such file or directory, open ...的解决办法。这个原因就是因为项目没有进行初始化,缺少package.json文件造成的。需要package.json才能npm install。 可以npm init初始化生成一个package.json。

npm命令大全_整理NPM常用命令

NPM是随同NodeJS一起安装的包管理和分发工具,它很方便让JavaScript开发者下载、安装、上传以及管理已经安装的包。这篇文章整理NPM常用的一些命令

npm 执行多个命令_如何用npm同时执行多条监听命令

npm 执行多个命令_如何用npm同时执行多条监听命令

直接通过&&连接多条命令,在npm run start的时候,发现只停留在第一个命令执行监听,后面的命令都没有执行。只能通过打开多个窗口分别执行多条命令,那么有没有办法实现一条npm命令执行多条监听呢?

在5分钟内搭建企业内部私有npm仓库

下面通过三种方法来搭建公司私有npm仓库,每种方式都有自己的优势。启动并配置服务、设置注册地址、登录cnpm、包上传到私有仓库、查看预览包、通过verdaccio搭建....

关于 npm run eject 报错的问题

关于 npm run eject 报错的问题,昨天新开React的项目, 刚刚一上手就碰到问题,解决方法(前提你有git).出错的原因:应该是git没有安装好,或者代码没有提交上git

npm install卡顿问题解决

安装angular cli工具时,发现进度条一直卡住不动,相信很多朋友也遇到过。原因应该是国内的网络连接npm速度较慢,甚至很多东西都无法下载安装。那么如何解决这个问题呢?

使用webpack开发npm插件

使用webpack开发npm插件

webpack:解析js文件,无法解析的文件需要借助loader,npm插件发布(vue&webpack&单页面):npm init =>package.json,创建.vue文件 =>插件界面及功能,index.js =>入口文件

vue-cli 3.x 开发插件并发布到 npm

抽空写了一个 textarea,打算发布到 npm 的时候却遇到了问题,之前用 vue-cli 2.x 的时候,打包配置项非常透明,可以很容易的修改,但升级到 vue-cli 3.x 之后,反而一脸懵逼

npm和bower的关系和区别

npm和bower的关系和区别

npm和bower太像了,就像一对孪生兄弟…… npm的文件是package.json,包安装的目录是node_modules。 bower的文件是bower.json,包安装的目录是bower_components。使用命令也基本一致

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!