clipboard-copy、copy-to-clipboard、ngclipboard、react-copy-to-clipboard 和 vue-clipboard2 都是用于在浏览器中实现文本复制到系统剪贴板功能的 npm 包,但它们面向不同的技术栈和使用场景。clipboard-copy 是一个极简的原生 JavaScript 工具函数,不依赖任何框架;copy-to-clipboard 同样是框架无关的通用库,提供 Promise 支持和更完整的错误处理;ngclipboard 是为 Angular 应用设计的指令封装;react-copy-to-clipboard 专为 React 提供组件和 Hook 式 API;vue-clipboard2 则是为 Vue 2 生态构建的插件(注意:官方已明确不再维护,且不支持 Vue 3)。这些库的核心目标一致 —— 安全、可靠地调用现代 Clipboard API 或回退到传统方案(如临时 textarea)以完成复制操作。
在 Web 应用中实现“一键复制”功能看似简单,实则涉及浏览器兼容性、安全策略(如用户手势要求)、API 降级(从现代 Clipboard API 回退到 document.execCommand)等复杂细节。上述五个库都试图简化这一过程,但设计理念、适用场景和技术栈绑定程度差异显著。本文将从核心能力、API 设计、错误处理和框架集成四个维度进行深度剖析。
所有库都优先尝试使用 现代 Clipboard API(navigator.clipboard.writeText),因其更安全、异步且无需创建 DOM 元素。若不可用(如旧版浏览器或非安全上下文),则回退到 document.execCommand('copy') 方案 —— 通过动态创建隐藏的 <textarea>,聚焦后执行命令。
clipboard-copy 采用最简实现:直接调用 writeText,失败时静默回退到 execCommand,不暴露错误信息。
// clipboard-copy
import copy from 'clipboard-copy';
copy('要复制的文本'); // 无返回值,无错误处理
copy-to-clipboard 同样自动降级,但返回 Promise,并在所有路径下统一 resolve/reject,便于业务逻辑判断。
// copy-to-clipboard
import copy from 'copy-to-clipboard';
copy('文本').then(success => {
if (success) console.log('复制成功');
else console.warn('复制失败');
});
ngclipboard、react-copy-to-clipboard 和 vue-clipboard2 均基于上述两种底层方案之一(通常是 copy-to-clipboard 或自实现),在其上增加框架层抽象,因此错误处理能力取决于底层实现。
⚠️ 注意:
vue-clipboard2的底层实现较旧,部分场景下在 iOS Safari 中可能失效,且无活跃维护修复。
clipboard-copy 提供纯函数接口,调用即执行,无状态:
import clipboardCopy from 'clipboard-copy';
document.getElementById('btn').onclick = () => {
clipboardCopy('Hello World');
};
copy-to-clipboard 同样是函数式,但支持选项配置(如是否使用 execCommand 强制回退):
import copy from 'copy-to-clipboard';
copy('文本', { format: 'text/plain' }); // 支持 MIME 类型(仅 Clipboard API 有效)
react-copy-to-clipboard 提供两种用法:
import { CopyToClipboard } from 'react-copy-to-clipboard';
function App() {
return (
<CopyToClipboard text="要复制的内容" onCopy={() => alert('已复制')}>
<button>复制</button>
</CopyToClipboard>
);
}
import { useCopyToClipboard } from 'react-copy-to-clipboard';
function App() {
const [value, copy] = useCopyToClipboard();
return (
<button onClick={() => copy('动态文本')}>
{value ? '✅ 复制成功' : '复制'}
</button>
);
}
ngclipboard 通过指令实现,符合 Angular 模板语法:
// app.module.ts
import { NgClipBoardModule } from 'ngclipboard';
@NgModule({ imports: [NgClipBoardModule] })
<!-- template.html -->
<button
ngclipboard
[cbContent]="'要复制的文本'"
(cbOnSuccess)="onCopied()"
(cbOnError)="onError($event)">
复制
</button>
vue-clipboard2 作为插件注册全局指令:
// main.js
import VueClipboard from 'vue-clipboard2';
Vue.use(VueClipboard);
<!-- component.vue -->
<template>
<button v-clipboard:copy="text" v-clipboard:success="onCopy">复制</button>
</template>
<script>
export default {
data() { return { text: 'Hello' }; },
methods: {
onCopy() { alert('成功'); }
}
}
</script>
❗ 重要提示:
vue-clipboard2官方仓库(https://github.com/Inndy/vue-clipboard2)已明确标注 “This project is no longer maintained.”,且无 Vue 3 支持计划。新项目应避免使用。
| 包名 | 错误反馈方式 | 是否可捕获失败原因 |
|---|---|---|
clipboard-copy | 无 | ❌ |
copy-to-clipboard | Promise reject / 回调 | ✅ |
ngclipboard | (cbOnError) 事件 | ✅(依赖底层) |
react-copy-to-clipboard | onCopy 回调参数 | ✅(依赖底层) |
vue-clipboard2 | v-clipboard:error 事件 | ⚠️(部分场景失效) |
例如,copy-to-clipboard 能明确区分是权限拒绝还是 API 不可用:
import copy from 'copy-to-clipboard';
copy('test').catch(err => {
if (err.name === 'NotAllowedError') {
alert('请允许剪贴板权限');
} else {
alert('浏览器不支持');
}
});
而 clipboard-copy 在相同场景下会静默失败,开发者无法感知。
clipboard-copy 和 copy-to-clipboard 是框架无关库,可安全用于任何项目,包括 Svelte、Solid 或原生 JS。两者均保持更新以适配浏览器变更。ngclipboard 专为 Angular 设计,但最近版本发布间隔较长,需自行验证与 Angular 16+/17 的兼容性。react-copy-to-clipboard 积极维护,支持 React 18 并提供 Hook API,是 React 项目的首选。vue-clipboard2 已废弃,不应在新项目中使用。Vue 3 用户应考虑:
copy-to-clipboard 封装自定义指令;@vueuse/core 的 useClipboard。clipboard-copycopy-to-clipboardreact-copy-to-clipboardngclipboard(需验证兼容性)copy-to-clipboard,避免指令依赖。vue-clipboard2(因历史原因)copy-to-clipboard + 自定义指令。| 特性 | clipboard-copy | copy-to-clipboard | ngclipboard | react-copy-to-clipboard | vue-clipboard2 |
|---|---|---|---|---|---|
| 框架绑定 | 无 | 无 | Angular | React | Vue 2 |
| API 风格 | 函数 | 函数 | 指令 | 组件/Hook | 指令 |
| 错误处理 | 无 | Promise/回调 | 事件 | 回调 | 事件(部分失效) |
| 维护状态 | 活跃 | 活跃 | 低频更新 | 活跃 | 已废弃 |
| 适用新项目 | ✅ | ✅ | ⚠️ | ✅ | ❌ |
copy-to-clipboard:它在通用性、健壮性和易用性之间取得了最佳平衡,即使你在 React/Angular 项目中,也可将其作为底层依赖自行封装。react-copy-to-clipboard:省去封装成本,享受框架优化。vue-clipboard2:技术债风险高,替代方案成熟。clipboard-copy:牺牲错误处理换取极致轻量。剪贴板操作虽小,却直接影响用户体验。选对工具,能让“复制”这一简单动作变得既可靠又优雅。
选择 react-copy-to-clipboard 如果你正在开发 React 应用,并希望以组件或自定义 Hook 的形式集成复制功能。它提供 <CopyToClipboard> 组件和 useCopyToClipboard Hook(需 v5.1+),能无缝融入 React 状态管理,适合需要响应式 UI 反馈(如按钮文字变化)的交互场景。
选择 vue-clipboard2 仅当你维护的是 Vue 2 遗留项目,且无法升级或替换方案。该库通过 Vue 插件形式注册全局指令 v-clipboard,使用简单。但官方 GitHub 明确标注“不再维护”,且完全不支持 Vue 3。新项目应避免使用,建议改用原生 Clipboard API 或 copy-to-clipboard 封装自定义指令。
选择 ngclipboard 如果你的项目基于 Angular(特别是 Angular 8+),并希望通过指令(directive)方式在模板中声明式地实现复制功能。它封装了底层细节,提供 cbContent、cbSuccess 等输入输出属性,符合 Angular 开发习惯。但需确认其与当前 Angular 版本的兼容性,因维护活跃度有限。
选择 clipboard-copy 如果你追求极致轻量、无依赖、仅需一行函数调用即可完成复制操作,且项目不涉及复杂的错误处理或 Promise 流程。它适合嵌入工具库、微前端子应用或对 bundle size 极度敏感的场景。但需注意它不返回 Promise,也不提供失败回调,仅适用于“尽力而为”式的简单复制需求。
选择 copy-to-clipboard 如果你需要一个跨框架、稳定可靠的通用解决方案,并希望获得 Promise 支持、明确的错误反馈以及对现代 Clipboard API 的自动降级处理。它适合大多数非框架绑定的项目,尤其是需要在业务逻辑中根据复制结果执行后续操作(如显示成功/失败提示)的场景。
Copy to clipboard React component
Based on copy-to-clipboard
Would try to use execCommand with fallback to IE specific clipboardData interface and finally, fallback to simple prompt with proper text content & 'Copy to clipboard: Ctrl+C, Enter'

yarn add react-copy-to-clipboard
npm install --save react-copy-to-clipboard
Don't forget to manually install peer dependencies (react) if you use npm@3.
https://nkbt.github.io/react-copy-to-clipboard
https://codepen.io/nkbt/pen/eNPoQv
import React from 'react';
import ReactDOM from 'react-dom';
import {CopyToClipboard} from 'react-copy-to-clipboard';
class App extends React.Component {
state = {
value: '',
copied: false,
};
render() {
return (
<div>
<input value={this.state.value}
onChange={({target: {value}}) => this.setState({value, copied: false})} />
<CopyToClipboard text={this.state.value}
onCopy={() => this.setState({copied: true})}>
<span>Copy to clipboard with span</span>
</CopyToClipboard>
<CopyToClipboard text={this.state.value}
onCopy={() => this.setState({copied: true})}>
<button>Copy to clipboard with button</button>
</CopyToClipboard>
{this.state.copied ? <span style={{color: 'red'}}>Copied.</span> : null}
</div>
);
}
}
const appRoot = document.createElement('div');
document.body.appendChild(appRoot);
ReactDOM.render(<App />, appRoot);
text: PropTypes.string.isRequiredText to be copied to clipboard
onCopy: PropTypes.funcOptional callback, will be called when text is copied
onCopy(text, result)
result (bool): Returns true if copied successfully, else false.
options: PropTypes.shape({debug: bool, message: string, format: string})Optional copy-to-clipboard options.
See API docs for details
children: PropTypes.element.isRequiredCopyToClipboard is a simple wrapping component, it does not render any tags, so it requires the only child element to be present, which will be used to capture clicks.
<CopyToClipboard text="Hello!">
<button>Copy to clipboard</button>
</CopyToClipboard>
Currently is being developed and tested with the latest stable Node on OSX.
To run example covering all CopyToClipboard features, use yarn start, which will compile example/Example.js
git clone git@github.com:nkbt/react-copy-to-clipboard.git
cd react-copy-to-clipboard
yarn install
yarn start
# then
open http://localhost:8080
# to run Biome check
yarn lint
# to run tests
yarn test
MIT