Clipboard 复制功能

Clipboard API 是浏览器提供的原生接口,允许开发者以编程方式访问和操作剪贴板内容。它支持复制和粘贴文本、图片等多种数据类型,且不依赖 Flash 或其他框架,具有良好的兼容性和性能。

📚 MDN 文档 Clipboard

前置知识

  • 安全性:剪贴板操作涉及用户隐私,需确保操作透明且获得用户授权。
  • 错误处理:由于剪贴板操作可能失败,建议使用 try-catch 捕获异常并提供友好的错误提示。
  • 兼容性处理:在不支持 Clipboard API 的浏览器中,可以使用 document.execCommand('copy')作为备用方案,但该方式已逐渐被淘汰。

1 Clipboard API

writeText(text):将指定的文本写入剪贴板。

async function copyText(text) {
  try {
    await navigator.clipboard.writeText(text);
    console.log("文本已复制到剪贴板");
  } catch (err) {
    console.error("复制失败:", err);
  }
}

readText():从剪贴板读取文本内容。

async function pasteText() {
  try {
    const text = await navigator.clipboard.readText();
    console.log("剪贴板内容:", text);
  } catch (err) {
    console.error("读取失败:", err);
  }
}

write(data):将任意类型的数据(如图片)写入剪贴板。

async function copyImage(imageBlob) {
  try {
    await navigator.clipboard.write([new ClipboardItem({ "image/png": imageBlob })]);
    console.log("图片已复制到剪贴板");
  } catch (err) {
    console.error("复制失败:", err);
  }
}

read():从剪贴板读取任意类型的数据。

async function pasteImage() {
  try {
    const clipboardItems = await navigator.clipboard.read();
    for (const item of clipboardItems) {
      if (item.types.includes("image/png")) {
        const blob = await item.getType("image/png");
        console.log("剪贴板中的图片:", blob);
      }
    }
  } catch (err) {
    console.error("读取失败:", err);
  }
}

2 权限管理

Clipboard API 的操作通常需要用户授权。可以通过 navigator.permissions.query 方法检查是否有权限访问剪贴板:

async function checkClipboardPermission() {
  const permission = await navigator.permissions.query({ name: "clipboard-write" });
  if (permission.state === "granted") {
    console.log("有权限访问剪贴板");
  } else {
    console.log("无权限访问剪贴板");
  }
}

3 兼容性

Clipboard API 在现代浏览器中得到了广泛支持,但某些旧版本浏览器可能不支持。可以通过以下方式检测兼容性:

在不支持 Clipboard API 的浏览器中,可以使用 document.execCommand('copy')作为备用方案,但该方式已逐渐被淘汰。

// 复制功能
const handleCopy = (url) => {
  if (!url) return proxy.$modal.msgWarning("请先选择游戏名称后复制");
  // 检查线上部署环境
  if (window.isSecureContext && navigator.clipboard) {
    navigator.clipboard
      .writeText(url)
      .then(() => {
        proxy.$modal.msgSuccess(`复制成功,已复制到粘贴板!`);
      })
      .catch((err) => {
        console.error("无法复制文本: ", err);
      });
  } else {
    // 非https等安全环境 需使用老方法 document.execCommand 官方随时会放弃
    let textArea = document.createElement("textarea");
    textArea.value = url;
    textArea.style.position = "absolute";
    textArea.style.opacity = 0;
    textArea.style.left = "-999999px";
    textArea.style.top = "-999999px";
    document.body.appendChild(textArea);
    textArea.focus();
    textArea.select();
    return new Promise((res, rej) => {
      // 执行复制命令并移除文本框
      document.execCommand("copy") ? res() : rej();
      textArea.remove();
      proxy.$modal.msgSuccess(`复制成功,已复制到粘贴板!`);
    });
  }
};
posted @   wanglei1900  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2022-03-06 【Vue2.x 随笔】如何初始化/清空所有data响应式数据 + 单独清空data响应式中的指定部分
点击右上角即可分享
微信分享提示