clipboard 和 copy-paste 都用于实现剪贴板读写功能,但它们的运行环境完全不同。clipboard(通常指 clipboard.js)是专为浏览器设计的库,它通过操作 DOM 元素来触发复制行为,兼容旧版浏览器。copy-paste 则是为 Node.js 环境设计的工具,它通过调用系统底层的命令行工具(如 Windows 的 clip.exe 或 macOS 的 pbcopy)来实现剪贴板访问。选择哪个包完全取决于你的代码运行在哪里 —— 前端页面还是后端脚本。
clipboard 和 copy-paste 虽然名字相似,但它们解决的是完全不同环境下的问题。一个是前端浏览器的 DOM 操作工具,另一个是后端 Node.js 的系统交互工具。理解这一核心差异是架构选型的关键。让我们从实际工程角度对比它们的实现机制。
clipboard 依赖浏览器环境。
document.execCommand 或 navigator.clipboard 的封装。// clipboard: 必须绑定到 DOM 元素
const ClipboardJS = require('clipboard');
const clipboard = new ClipboardJS('.btn');
// 假设 HTML 中有 <button class="btn" data-clipboard-text="Copy Me">
copy-paste 依赖 Node.js 环境。
child_process 调用操作系统的剪贴板工具。// copy-paste: 直接在 Node 环境中调用
const copyPaste = require('copy-paste');
const text = 'Copy Me';
copyPaste.copy(text, function (err) {
if (err) console.error(err);
});
clipboard 采用事件驱动模式。
success 或 error 事件。// clipboard: 事件监听模式
clipboard.on('success', function (e) {
console.info('Action:', e.action);
console.info('Text:', e.text);
e.clearSelection();
});
clipboard.on('error', function (e) {
console.error('Action:', e.action);
console.error('Trigger:', e.trigger);
});
copy-paste 采用回调函数模式。
copy 或 paste 函数。// copy-paste: 回调函数模式
const copyPaste = require('copy-paste');
copyPaste.copy('Hello World', function (err) {
if (!err) console.log('Copied to system clipboard');
});
copyPaste.paste(function (err, text) {
if (!err) console.log('Pasted text:', text);
});
clipboard 受浏览器安全策略限制。
// clipboard: 需要用户点击触发
// HTML: <button class="btn" data-clipboard-text="Secret">
// 如果尝试通过 JS 自动触发而不带用户手势,浏览器会拦截
copy-paste 受操作系统权限限制。
// copy-paste: 脚本可随时运行
// 在 CI/CD 脚本中自动复制构建日志
const copyPaste = require('copy-paste');
copyPaste.copy('Build Failed', function () {
// 即使没有用户操作也能执行
});
clipboard 是纯 JavaScript 实现。
// clipboard: 无系统依赖
// 直接打包进 webpack 或 Vite 即可使用
import ClipboardJS from 'clipboard';
copy-paste 依赖系统命令行工具。
clip.exe,macOS 需要 pbcopy/pbpaste,Linux 需要 xclip 或 xsel。// copy-paste: 依赖系统工具
// Linux 上可能需要先安装:sudo apt-get install xclip
copyPaste.copy('Text', function (err) {
// 如果没装 xclip,这里会报错
});
尽管环境不同,这两个库在解决剪贴板问题时有一些共通的设计理念。
// 两者都提供了跨平台统一接口
// clipboard: 自动处理 execCommand 与 navigator.clipboard
// copy-paste: 自动选择 clip.exe 或 pbcopy
// clipboard: 通过 error 事件
clipboard.on('error', (e) => { /* handle */ });
// copy-paste: 通过回调第一个参数
copyPaste.copy(text, (err) => { if (err) /* handle */ });
// 两者都是非阻塞的
// clipboard: 事件异步触发
// copy-paste: 回调异步执行
| 特性 | clipboard | copy-paste |
|---|---|---|
| 运行环境 | 🌐 浏览器 (Browser) | 🖥️ Node.js (Server/CLI) |
| 核心依赖 | 📄 DOM 元素 | ⚙️ 系统二进制工具 |
| 触发方式 | 👆 用户手势 (点击) | 🤖 脚本自动执行 |
| API 风格 | 🎧 事件监听 (Events) | 📞 回调函数 (Callbacks) |
| 跨平台性 | ✅ 高 (纯 JS) | ⚠️ 中 (需系统工具支持) |
| 主要用途 | 网页交互复制 | 脚本自动化、CLI 工具 |
clipboard 是前端交互的标准选择 🎯。如果你正在构建 Web 应用,需要让用户点击按钮复制邀请码或链接,这是最成熟的方案。但要注意,随着 navigator.clipboard API 的普及,新项目可以直接使用原生 API,clipboard 更多用于兼容旧浏览器。
copy-paste 是 Node.js 脚本的实用工具 🛠️。适合构建命令行工具(如自动复制部署日志)或 Electron 应用。但需注意,该库维护频率较低,对于新的 Node.js 项目,建议评估 clipboardy 作为更现代的替代方案,它提供了更好的 Promise 支持和活跃度。
最终思考:这两个库并不竞争,而是互补。在一个全栈项目中,你可能在前端用 clipboard 处理用户交互,在后端用 copy-paste(或 clipboardy)处理服务器端的自动化任务。明确代码运行的环境,是选择正确工具的第一步。
如果你的代码运行在浏览器环境中,并且需要兼容旧版浏览器或不支持异步 Clipboard API 的场景,选择 clipboard。它通过事件绑定到 DOM 元素上,适合处理用户点击按钮复制文本的交互场景,无需关心底层系统命令。
如果你的代码运行在 Node.js 环境(如 CLI 工具、服务器脚本或 Electron 主进程),选择 copy-paste。它允许你在没有浏览器的情况下访问系统剪贴板。但请注意,对于现代 Node.js 项目,社区更倾向于推荐 clipboardy 作为更活跃的替代方案。
Modern copy to clipboard. No Flash. Just 3kb gzipped.
Copying text to the clipboard shouldn't be hard. It shouldn't require dozens of steps to configure or hundreds of KBs to load. But most of all, it shouldn't depend on Flash or any bloated framework.
That's why clipboard.js exists.
You can get it on npm.
npm install clipboard --save
Or if you're not into package management, just download a ZIP file.
First, include the script located on the dist folder or load it from a third-party CDN provider.
<script src="dist/clipboard.min.js"></script>
Now, you need to instantiate it by passing a DOM selector, HTML element, or list of HTML elements.
new ClipboardJS('.btn');
Internally, we need to fetch all elements that matches with your selector and attach event listeners for each one. But guess what? If you have hundreds of matches, this operation can consume a lot of memory.
For this reason we use event delegation which replaces multiple event listeners with just a single listener. After all, #perfmatters.
We're living a declarative renaissance, that's why we decided to take advantage of HTML5 data attributes for better usability.
A pretty common use case is to copy content from another element. You can do that by adding a data-clipboard-target attribute in your trigger element.
The value you include on this attribute needs to match another's element selector.
<!-- Target -->
<input id="foo" value="https://github.com/zenorocha/clipboard.js.git" />
<!-- Trigger -->
<button class="btn" data-clipboard-target="#foo">
<img src="https://raw.githubusercontent.com/zenorocha/clipboard.js/HEAD/assets/clippy.svg" alt="Copy to clipboard" />
</button>
Additionally, you can define a data-clipboard-action attribute to specify if you want to either copy or cut content.
If you omit this attribute, copy will be used by default.
<!-- Target -->
<textarea id="bar">Mussum ipsum cacilds...</textarea>
<!-- Trigger -->
<button class="btn" data-clipboard-action="cut" data-clipboard-target="#bar">
Cut to clipboard
</button>
As you may expect, the cut action only works on <input> or <textarea> elements.
Truth is, you don't even need another element to copy its content from. You can just include a data-clipboard-text attribute in your trigger element.
<!-- Trigger -->
<button
class="btn"
data-clipboard-text="Just because you can doesn't mean you should — clipboard.js"
>
Copy to clipboard
</button>
There are cases where you'd like to show some user feedback or capture what has been selected after a copy/cut operation.
That's why we fire custom events such as success and error for you to listen and implement your custom logic.
var clipboard = new ClipboardJS('.btn');
clipboard.on('success', function (e) {
console.info('Action:', e.action);
console.info('Text:', e.text);
console.info('Trigger:', e.trigger);
e.clearSelection();
});
clipboard.on('error', function (e) {
console.error('Action:', e.action);
console.error('Trigger:', e.trigger);
});
For a live demonstration, go to this site and open your console.
Each application has different design needs, that's why clipboard.js does not include any CSS or built-in tooltip solution.
The tooltips you see on the demo site were built using GitHub's Primer. You may want to check that out if you're looking for a similar look and feel.
If you don't want to modify your HTML, there's a pretty handy imperative API for you to use. All you need to do is declare a function, do your thing, and return a value.
For instance, if you want to dynamically set a target, you'll need to return a Node.
new ClipboardJS('.btn', {
target: function (trigger) {
return trigger.nextElementSibling;
},
});
If you want to dynamically set a text, you'll return a String.
new ClipboardJS('.btn', {
text: function (trigger) {
return trigger.getAttribute('aria-label');
},
});
For use in Bootstrap Modals or with any other library that changes the focus you'll want to set the focused element as the container value.
new ClipboardJS('.btn', {
container: document.getElementById('modal'),
});
Also, if you are working with single page apps, you may want to manage the lifecycle of the DOM more precisely. Here's how you clean up the events and objects that we create.
var clipboard = new ClipboardJS('.btn');
clipboard.destroy();
This library relies on both Selection and execCommand APIs. The first one is supported by all browsers while the second one is supported in the following browsers.
![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
|---|---|---|---|---|---|
| 42+ ✔ | 12+ ✔ | 41+ ✔ | 9+ ✔ | 29+ ✔ | 10+ ✔ |
The good news is that clipboard.js gracefully degrades if you need to support older browsers. All you have to do is show a tooltip saying Copied! when success event is called and Press Ctrl+C to copy when error event is called because the text is already selected.
You can also check if clipboard.js is supported or not by running ClipboardJS.isSupported(), that way you can hide copy/cut buttons from the UI.
A browser extension that adds a "copy to clipboard" button to every code block on GitHub, MDN, Gist, StackOverflow, StackExchange, npm, and even Medium.
Install for Chrome and Firefox.
MIT License © Zeno Rocha