与剪贴板交互

扩展程序中处理剪贴板的操作正从 Web API 的 `document.execCommand` 方法(已弃用)过渡到 `navigator.clipboard` 方法。

注意: `navigator.clipboard` API 是规范中较新的部分,可能尚未在所有浏览器中完全实现。本文档介绍了一些限制,但在使用它们之前,请务必查看每种方法的兼容性表格,以确保 API 符合您的需求。

两种 API 的区别在于,`document.execCommand` 类似于键盘的复制、剪切和粘贴操作——在网页和剪贴板之间交换数据——而 `navigator.clipboard` 则向剪贴板读写任意数据。

`navigator.clipboard` 分别提供了读取或写入的方法。

  • 文本内容,使用 `navigator.clipboard.readText()` 和 `navigator.clipboard.writeText()`。
  • 图像、富文本、HTML 和其他富媒体内容,使用 `navigator.clipboard.read()` 和 `navigator.clipboard.write()`。

然而,虽然 `navigator.clipboard.readText()` 和 `navigator.clipboard.writeText()` 在所有浏览器上都能正常工作,但 `navigator.clipboard.read()` 和 `navigator.clipboard.write()` 却不行。例如,在撰写本文时,Firefox 中的 `navigator.clipboard.read()` 和 `navigator.clipboard.write()` 尚未完全实现,因此要

  • 处理图像,可以使用 `browser.clipboard.setImageData()` 将图像写入剪贴板,并使用 `document.execCommand("paste")` 将图像粘贴到网页上。
  • 要将富媒体内容(例如 HTML、包含图像的富文本等)写入剪贴板,请使用 `document.execCommand("copy")` 或 `document.execCommand("cut")`。然后,可以使用 `navigator.clipboard.read()`(推荐)或 `document.execCommand("paste")` 从剪贴板读取内容。

写入剪贴板

本节介绍将数据写入剪贴板的选项。

使用剪贴板 API

剪贴板 API 可以将任意数据从您的扩展程序写入剪贴板。使用该 API 需要在 `manifest.json` 文件中具有 `clipboardRead` 或 `clipboardWrite` 权限。由于该 API 仅在 安全上下文 中可用,因此不能从在 `http:` 页面上运行的内容脚本中使用,只能在 `https:` 页面上使用。

对于页面脚本,需要使用 Web API `navigator.permissions` 请求 `clipboard-write` 权限。您可以使用 `navigator.permissions.query()` 来检查该权限。

js
navigator.permissions.query({ name: "clipboard-write" }).then((result) => {
  if (result.state === "granted" || result.state === "prompt") {
    /* write to the clipboard now */
  }
});

注意: `clipboard-write` 权限名称在 Firefox 中不受支持,仅在 Chromium 浏览器中受支持。

此函数接受一个字符串并将其写入剪贴板。

js
function updateClipboard(newClip) {
  navigator.clipboard.writeText(newClip).then(
    () => {
      /* clipboard successfully set */
    },
    () => {
      /* clipboard write failed */
    },
  );
}

使用 execCommand()

`document.execCommand()` 方法的 `"cut"` 和 `"copy"` 命令用于将选中的内容替换剪贴板的内容。在用户操作的短暂事件处理程序中(例如,点击处理程序)使用这些命令无需特殊权限。

例如,假设您的弹出窗口包含以下 HTML

html
<input id="input" type="text" /> <button id="copy">Copy</button>

要让 `"copy"` 按钮复制 `` 元素的内容,您可以使用类似这样的代码:

js
function copy() {
  let copyText = document.querySelector("#input");
  copyText.select();
  document.execCommand("copy");
}

document.querySelector("#copy").addEventListener("click", copy);

由于 `execCommand()` 调用位于点击事件处理程序中,您不需要任何特殊权限。

但是,假设您从一个警报触发复制:

js
function copy() {
  let copyText = document.querySelector("#input");
  copyText.select();
  document.execCommand("copy");
}

browser.alarms.create({
  delayInMinutes: 0.1,
});

browser.alarms.onAlarm.addListener(copy);

这可能不起作用,具体取决于浏览器。在 Firefox 中,它将不起作用,并且您将在控制台中看到类似如下的消息:

document.execCommand('cut'/'copy') 被拒绝,因为它不是在短暂的用户生成事件处理程序中调用的。

为了启用此用例,您需要申请 `clipboardWrite` 权限。因此:`"clipboardWrite"` 使您能够在用户操作的短暂事件处理程序之外写入剪贴板。

注意: `document.execCommand()` 不适用于 `type="hidden"` 的输入字段、带有 HTML5 属性 `"hidden"` 的元素,或使用 `display: none;` 的任何匹配 CSS 规则。因此,要为 `span`、`div` 或 `p` 标签添加“复制到剪贴板”按钮,您需要使用一种解决方法,例如将输入框的位置设置为绝对定位并将其移出视口。

浏览器特定注意事项

剪贴板和其他涉及的 API 正在快速发展,因此浏览器在工作方式上存在差异。

在 Chrome 中

  • 即使在用户生成的事件处理程序之外写入剪贴板,您也不需要 `clipboardWrite`。

在 Firefox 中

  • `navigator.clipboard.write()` 不受支持。

有关更多信息,请参阅 浏览器兼容性表格

从剪贴板读取

本节介绍从剪贴板读取或粘贴数据的选项。

使用剪贴板 API

剪贴板 API 的 `navigator.clipboard.readText()` 和 `navigator.clipboard.read()` 方法允许您在 安全上下文 中从剪贴板读取任意文本或二进制数据。这使您无需将其粘贴到可编辑元素中即可访问剪贴板中的数据。

一旦从 Permissions API 获得 `clipboard-read` 权限,您就可以轻松地从剪贴板读取。例如,这段代码从剪贴板获取文本,并用该文本替换 ID 为 `outbox` 的元素的内容。

js
navigator.clipboard
  .readText()
  .then((clipText) => (document.getElementById("outbox").innerText = clipText));

使用 execCommand()

要使用 `document.execCommand("paste")`,您的扩展需要 `clipboardRead` 权限。即使您在用户生成的事件处理程序(如 clickkeypress)中使用 `"paste"` 命令,也是如此。

考虑包含类似内容的 HTML:

html
<textarea id="output"></textarea> <button id="paste">Paste</button>

要当用户点击 `"paste"` `