Async Clipboard API:读写剪贴板
一句话: Async Clipboard API——navigator.clipboard——让你以编程方式读写系统剪贴板。
写入纯文本无需权限;读取操作受到严格管控:Chromium 可能使用 clipboard-read 权限,
而 Firefox 和 Safari 则需要瞬态激活(transient activation)和浏览器自身的粘贴提示框
(不存储持久权限)。所有操作均需要安全上下文(HTTPS 或 localhost)。
纯文本(最常见)
Section titled “纯文本(最常见)”try { await navigator.clipboard.writeText('你好,剪贴板!');} catch (err) { console.error('剪贴板写入失败:', err);}writeText 要求:
- 安全上下文(HTTPS 或
localhost)。 - 具有用户激活或页面获得焦点(具体规则因浏览器而异,但在点击处理器中调用 始终安全)。
富内容(图片、HTML)
Section titled “富内容(图片、HTML)”const blob = new Blob(['<b>你好</b>'], { type: 'text/html' });const item = new ClipboardItem({ 'text/html': blob });await navigator.clipboard.write([item]);write() 接受 ClipboardItem 对象数组。每个 item 可携带多种 MIME 类型,让粘贴目标
选择它所理解的最丰富格式。
从剪贴板读取
Section titled “从剪贴板读取”const text = await navigator.clipboard.readText();const items = await navigator.clipboard.read();for (const item of items) { for (const type of item.types) { const blob = await item.getType(type); // 处理 blob }}权限行为因浏览器系列差异显著。
Chromium(Chrome、Edge、Opera)
Section titled “Chromium(Chrome、Edge、Opera)”Chromium 使用 clipboard-read 和 clipboard-write 作为 Permissions API 的权限名称:
- 写入(
writeText/write):在已聚焦、有用户激活的上下文中调用writeText时无需权限提示。对某些 MIME 类型(如图片)调用write()可能会触发clipboard-write权限提示。 - 读取(
readText/read):需要clipboard-read权限;首次读取时浏览器 会显示提示。可以不触发提示查询当前状态:
// 仅限 Chromium —— clipboard-read 在 Firefox 或 Safari 中不是合法的权限名称const { state } = await navigator.permissions.query({ name: 'clipboard-read' });// state: 'granted' | 'denied' | 'prompt'Firefox
Section titled “Firefox”Firefox 不将 clipboard-read 或 clipboard-write 识别为 Permissions API 权限
名称——navigator.permissions.query({ name: 'clipboard-read' }) 会被拒绝或返回无意义
的状态。Firefox 的行为是:
- 写入:需要瞬时激活(用户手势,如点击)。
- 读取:需要瞬时激活,并触发一次性浏览器粘贴确认对话框,用户必须确认;不存在 持久授权。
Safari
Section titled “Safari”Safari 同样不通过 Permissions API 暴露 clipboard-read/clipboard-write,其
模型与 Firefox 类似:
- 写入:需要瞬时激活。
- 读取:需要瞬时激活和用户发起的粘贴提示;不存储持久权限。
安全上下文(HTTPS)
Section titled “安全上下文(HTTPS)”navigator.clipboard 仅在安全上下文(HTTPS 或 localhost)中可用。在普通 HTTP
下,该属性为 undefined。
用户手势与焦点要求
Section titled “用户手势与焦点要求”读写操作应在用户手势处理器内或文档已获得焦点时调用。各浏览器细节略有不同,但在
click 处理器中调用始终安全。在无用户激活的上下文中调用通常会导致 NotAllowedError。
回退:document.execCommand
Section titled “回退:document.execCommand”传统的 document.execCommand('copy') 和 document.execCommand('paste') 在旧版浏览器
中可用,但已废弃,且不支持富内容。仅作最后手段使用:
function legacyCopy(text) { const textarea = document.createElement('textarea'); textarea.value = text; document.body.appendChild(textarea); textarea.select(); document.execCommand('copy'); textarea.remove();}浏览器与生态支持
Section titled “浏览器与生态支持”当前各浏览器数据请参见 /compatibility/。
决策判定框架
Section titled “决策判定框架”| 决策问题 | 建议行为 | 理由 |
|---|---|---|
| 点击按钮时复制纯文本? | 在点击处理器中调用 navigator.clipboard.writeText()。 |
无权限提示;所有现代浏览器在 HTTPS 下均可用。 |
| 将图片或 HTML 复制到剪贴板? | navigator.clipboard.write([new ClipboardItem(...)])。 |
支持多格式载荷;粘贴目标选择最佳类型。 |
| 读取剪贴板内容? | 始终在用户手势处理器中调用。在 Chromium 中可先查询 clipboard-read 权限;在 Firefox 和 Safari 中依赖瞬时激活和浏览器自身的粘贴提示,不要使用 navigator.permissions.query。 |
权限模型因浏览器系列而异;瞬时激活是可移植的基线。 |
| 需要支持旧版浏览器? | 特性检测 navigator.clipboard;回退到 execCommand。 |
execCommand 已废弃但在旧引擎中仍可用。 |
| 在 Service Worker 或后台上下文中访问剪贴板? | 不可能——剪贴板访问需要已聚焦的文档。 | 按规范和浏览器策略,剪贴板在后台上下文中不可用。 |
- 通过 HTTPS 提供页面——普通 HTTP 下
navigator.clipboard为 undefined。 - 在用户手势处理器内或文档已获焦点时调用剪贴板方法。
- 纯文本用
writeText;富内容用带ClipboardItem的write。 - 始终在用户手势处理器中调用读取方法。在 Chromium 中可选择先查询
clipboard-read权限状态;在 Firefox 和 Safari 中依赖瞬时激活和浏览器粘贴提示——navigator.permissions.query({ name: 'clipboard-read' })不能跨浏览器系列移植。 - 捕获所有剪贴板调用的错误——权限可能被拒绝或撤销。
- 为不支持 Async Clipboard API 的浏览器提供
document.execCommand回退。