中文 | English
现代剪贴板工具库 -- 零依赖,支持浏览器和 Node.js 双环境。
- 现代 API 优先 -- 优先使用
navigator.clipboard.writeText(),自动降级到document.execCommand - Promise 异步 -- 所有操作返回 Promise,支持 async/await
- 自动重试 -- 内置可配置的指数退避重试机制,支持超时控制
- 双环境支持 -- 浏览器 + Node.js(Windows
clip/ macOSpbcopy/ Linuxxclip/xsel) - 读写双向 -- 支持写入(复制/剪切)和读取(粘贴)剪贴板
- 粘贴监听 -- 通过
onPaste监听粘贴事件,自动解析文本、HTML、文件 - 权限检测 -- 通过
queryPermission查询剪贴板读写权限状态 - HTML 属性绑定 -- 通过
data-nc-*属性声明式绑定复制行为 - 事件委托 -- 支持选择器字符串、Element、NodeList 三种触发方式
- 资源安全 -- 完善的
destroy()方法防止内存泄漏 - 图片复制 -- 支持 Blob、File、HTMLImageElement、HTMLCanvasElement、URL 等多种图片源
- 富文本复制 -- 同时复制 HTML + 纯文本,自动降级到 execCommand
- TypeScript -- 内置完整的
.d.ts类型定义 - ESM 支持 -- 提供 ESM 模块版本,支持
import语法和 Tree-shaking - 零依赖 -- 单文件,无任何外部依赖
| 文件 | 说明 |
|---|---|
NowClipboard.js |
完整版(带注释,便于阅读和调试) |
NowClipboard.min.js |
压缩版(生产环境推荐) |
NowClipboard.esm.mjs |
ESM 模块版本(支持 import 语法) |
NowClipboard.d.ts |
TypeScript 类型定义文件 |
npm install nowclipboard --save<!-- 开发环境 -->
<script src="NowClipboard.js"></script>
<!-- 生产环境(推荐) -->
<script src="NowClipboard.min.js"></script>var NowClipboard = require('nowclipboard');require(['NowClipboard'], function (NowClipboard) {
// ...
});// 默认导入
import NowClipboard from 'nowclipboard';
// 命名导入(按需引入)
import { copy, read, copyImage, copyRich } from 'nowclipboard';通过 data-nc-* 属性指定复制行为,无需写额外 JS 逻辑:
<!-- 复制指定文本 -->
<button class="btn" data-nc-text="要复制的内容">复制文本</button>
<!-- 复制目标元素的内容 -->
<input id="source" value="输入框内容">
<button class="btn" data-nc-target="#source">复制输入框</button>
<!-- 剪切目标元素的内容 -->
<textarea id="content">可编辑内容</textarea>
<button class="btn" data-nc-target="#content" data-nc-action="cut">剪切</button><script src="NowClipboard.js"></script>
<script>
var clipboard = new NowClipboard('.btn');
clipboard.on('success', function (e) {
console.log('复制成功:', e.text);
e.clearSelection();
});
clipboard.on('error', function (e) {
console.error('复制失败:', e.error);
});
</script>通过函数动态控制复制行为:
var clipboard = new NowClipboard('.btn', {
// 自定义操作类型
action: function (trigger) {
return trigger.getAttribute('data-action') || 'copy';
},
// 自定义目标元素
target: function (trigger) {
var id = trigger.getAttribute('data-target');
return document.getElementById(id);
},
// 自定义复制文本
text: function (trigger) {
return '当前时间: ' + new Date().toLocaleString();
},
// 容器元素(用于降级方案中的临时元素挂载)
container: document.body,
// 重试配置
retries: 3, // 最大重试次数(默认 2)
retryDelay: 200, // 基础延迟 ms(默认 100,指数退避)
timeout: 5000 // 超时 ms(默认 0,不超时)
});不需要实例化,直接复制文本:
// 复制文本
NowClipboard.copy('Hello World')
.then(function (text) {
console.log('已复制:', text);
})
.catch(function (err) {
console.error('失败:', err.message);
});
// async/await 写法
async function doCopy() {
try {
var text = await NowClipboard.copy('Hello World');
console.log('已复制:', text);
} catch (err) {
console.error('失败:', err.message);
}
}var textarea = document.querySelector('#myTextarea');
NowClipboard.cut(textarea).then(function (text) {
console.log('已剪切:', text);
});// 浏览器(需要 HTTPS + 用户授权)
NowClipboard.read().then(function (text) {
console.log('剪贴板内容:', text);
});
// 带配置
NowClipboard.read({ retries: 3, timeout: 3000 }).then(function (text) {
console.log('读取成功:', text);
});// 监听整个页面的粘贴事件
var listener = NowClipboard.onPaste(null, function (data) {
console.log('文本:', data.text);
console.log('HTML:', data.html);
console.log('文件:', data.files);
// data.originalEvent 为原始 paste 事件
});
// 监听指定选择器(事件委托)
var listener2 = NowClipboard.onPaste('.paste-area', function (data) {
console.log('粘贴到目标区域:', data.text);
});
// 销毁监听
listener.destroy();// 检测读取权限
NowClipboard.queryPermission('read').then(function (result) {
console.log('读取权限:', result.state); // 'granted', 'denied', 或 'prompt'
});
// 检测写入权限
NowClipboard.queryPermission('write').then(function (result) {
console.log('写入权限:', result.state);
});需要 HTTPS + 现代浏览器(支持 ClipboardItem API)。
// 复制图片 URL
NowClipboard.copyImage('https://example.com/photo.png')
.then(function (blob) {
console.log('图片已复制,大小:', blob.size);
});
// 复制 Canvas 画布
var canvas = document.querySelector('#myCanvas');
NowClipboard.copyImage(canvas);
// 复制 img 元素
var img = document.querySelector('#myImage');
NowClipboard.copyImage(img);
// 复制任意 Blob
var blob = new Blob([data], { type: 'image/png' });
NowClipboard.copyBlob(blob);同时复制 HTML 和纯文本,粘贴时保留格式。
NowClipboard.copyRich({
text: '纯文本内容',
html: '<b>加粗</b>的 <em>富文本</em> 内容'
}).then(function (result) {
console.log('已复制:', result.text, result.html);
});通过 HTML 属性绑定富文本复制:
<div id="rich-content">
<h3>标题</h3>
<p>这是 <strong>加粗</strong> 的内容</p>
</div>
<button class="btn" data-nc-target="#rich-content" data-nc-html="true">
复制富文本
</button>var NowClipboard = require('./NowClipboard.js');
NowClipboard.copy('从服务端复制的内容').then(function (text) {
console.log('已写入系统剪贴板:', text);
}).catch(function (err) {
console.error('失败:', err.message);
});
// 读取系统剪贴板
NowClipboard.read().then(function (text) {
console.log('剪贴板内容:', text);
});Node.js 系统命令依赖:
| 操作系统 | 写入命令 | 读取命令 | 备注 |
|---|---|---|---|
| Windows | clip |
powershell Get-Clipboard |
系统内置 |
| macOS | pbcopy |
pbpaste |
系统内置 |
| Linux | xclip |
xclip -o |
需安装:sudo apt install xclip |
| Linux (降级) | xsel |
xsel -o |
备选:sudo apt install xsel |
new NowClipboard(trigger, [options])| 参数 | 类型 | 说明 |
|---|---|---|
trigger |
string | Element | NodeList |
CSS 选择器、DOM 元素或元素集合 |
options.action |
Function |
(trigger) => 'copy' | 'cut' |
options.target |
Function |
(trigger) => Element |
options.text |
Function |
(trigger) => string |
options.container |
Element |
容器元素,默认 document.body |
options.retries |
number |
最大重试次数,默认 2 |
options.retryDelay |
number |
基础重试延迟 ms,默认 100(指数退避) |
options.timeout |
number |
超时 ms,默认 0(不超时) |
| 方法 | 说明 |
|---|---|
.on(event, handler) |
注册事件监听 |
.once(event, handler) |
注册一次性事件监听 |
.off(event, handler) |
移除事件监听 |
.destroy() |
销毁实例,移除所有事件监听和 DOM 绑定 |
| 方法 | 返回值 | 说明 |
|---|---|---|
NowClipboard.copy(text, [options]) |
Promise<string> |
复制文本到剪贴板 |
NowClipboard.cut(element) |
Promise<string> |
剪切元素内容(仅浏览器) |
NowClipboard.read([options]) |
Promise<string> |
读取剪贴板文本 |
NowClipboard.copyImage(source, [options]) |
Promise<Blob> |
复制图片(支持 Blob/File/Img/Canvas/URL) |
NowClipboard.copyBlob(blob, [mimeType], [options]) |
Promise<Blob> |
复制任意 Blob 到剪贴板 |
NowClipboard.copyRich(options) |
Promise<{text, html}> |
复制富文本(HTML + 纯文本) |
NowClipboard.onPaste(target, callback) |
{ destroy } |
监听粘贴事件(仅浏览器) |
NowClipboard.queryPermission(name) |
Promise<{ state }> |
查询剪贴板权限('read'/'write') |
NowClipboard.checkSupport([actions]) |
boolean |
检测环境是否支持剪贴板操作 |
复制/剪切操作成功时触发。
clipboard.on('success', function (e) {
e.action; // 'copy' 或 'cut'
e.text; // 复制的文本内容
e.trigger; // 触发操作的 DOM 元素
e.clearSelection(); // 清除页面选区
});操作失败时触发。
clipboard.on('error', function (e) {
e.action; // 'copy' 或 'cut'
e.trigger; // 触发操作的 DOM 元素
e.error; // Error 对象,包含失败原因
e.clearSelection(); // 清除页面选区
});| 属性 | 说明 | 示例 |
|---|---|---|
data-nc-text |
指定要复制的文本 | data-nc-text="复制我" |
data-nc-target |
指定目标元素的 CSS 选择器 | data-nc-target="#input1" |
data-nc-action |
操作类型:copy(默认)或 cut |
data-nc-action="cut" |
data-nc-html |
启用富文本复制模式 | data-nc-html="true" |
库会自动按以下顺序尝试最佳方案:
1. navigator.clipboard.writeText() (HTTPS + 现代浏览器)
|
v 失败
2. document.execCommand('copy') (HTTP + 旧浏览器)
|
v 失败
3. child_process (clip/pbcopy/xclip) (Node.js 环境)
|
v 失败
4. 抛出错误,触发 'error' 事件
每层失败后自动重试(默认最多 2 次,指数退避),重试次数、延迟和超时均可配置。
| 元素 | 复制 | 剪切 |
|---|---|---|
<input> |
支持 | 支持 |
<textarea> |
支持 | 支持 |
<select> |
支持 | -- |
contenteditable 元素 |
支持 | 支持 |
| 普通元素(div, span 等) | 支持 | -- |
NowClipboard 优先使用现代 Clipboard API,并自动降级到 execCommand 以支持旧版浏览器。
|
Chrome |
Edge |
Firefox |
Safari |
Opera |
IE |
| 66+ ✅ | 79+ ✅ | 63+ ✅ | 13.1+ ✅ | 53+ ✅ | 9+ ✅ |
| Clipboard API(现代方案) | execCommand(降级) | ||||
💡 如果需要支持旧版浏览器,NowClipboard 会自动降级到
execCommand方案。你只需在error事件中提示用户手动Ctrl+C即可。
| 对比项 | ClipboardJS | NowClipboard.js |
|---|---|---|
| 复制方式 | 仅 execCommand |
Clipboard API + execCommand 降级 |
| 图片复制 | 不支持 | 支持(Blob/File/Img/Canvas/URL) |
| 富文本复制 | 不支持 | 支持(HTML + 纯文本同时复制) |
| 读取剪贴板 | 不支持 | 支持(浏览器 + Node.js) |
| 粘贴监听 | 不支持 | 支持(onPaste + 自动解析) |
| 权限检测 | 不支持 | 支持(queryPermission) |
| 异步 | 同步 | Promise-based |
| 重试 | 无 | 可配置重试 + 指数退避 + 超时 |
| Node.js | 不支持 | 支持 (Win/Mac/Linux) |
| TypeScript | 无类型定义 | 内置 .d.ts 类型定义 |
| ESM | 不支持 | 支持(ESM + UMD 双格式) |
| 代码 | 压缩混淆 | 可读、带注释 |
| 销毁 | 基础 | 完善(防内存泄漏) |
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>NowClipboard Demo</title>
</head>
<body>
<input id="source" value="这是要复制的内容" style="width: 300px;">
<button class="copy-btn" data-nc-target="#source">复制输入框</button>
<button class="copy-btn" data-nc-text="直接复制这段文字">复制文本</button>
<p id="result"></p>
<script src="NowClipboard.js"></script>
<script>
var clipboard = new NowClipboard('.copy-btn');
var result = document.getElementById('result');
clipboard.on('success', function (e) {
result.textContent = '复制成功: ' + e.text;
e.clearSelection();
});
clipboard.on('error', function (e) {
result.textContent = '复制失败: ' + e.error.message;
});
</script>
</body>
</html>MIT