JS通过 navigator.clipboard.writeText(textToCopy) 实现文本复制,navigator.clipboard报undefined问题

发布时间 2023-06-07 10:13:24作者: 槑孒

问题描述

代码:

let geometries = qChart.value
  .filter((e) => e.geometry)
  .map((e) => e?.geometry);
navigator.clipboard
  .writeText(JSON.stringify(geometries))
  .then(() => {
    proxy.$modal.msgSuccess("已复制");
  })
  .catch(() => {
    proxy.$modal.msgSuccess("复制失败");
  });

测试环境下可以正常复制 ,但放到线上会报错:找不到 .writeText

问题分析

在 Chrome 的 DevTools 控制台下执行 navigator.clipboard 返回 undefined,经查找资料发现是浏览器禁用了非安全域的 navigator.clipboard 对象,哪些地址是安全的呢?

安全域包括本地访问与开启TLS安全认证的地址,如 https 协议的地址127.0.0.1localhost

解决方案

let geometries = qChart.value
    .filter((e) => e.geometry)
    .map((e) => e?.geometry);
if (navigator.clipboard && window.isSecureContext) {
  navigator.clipboard
    .writeText(JSON.stringify(geometries))
    .then(() => {
      proxy.$modal.msgSuccess("已复制");
    })
    .catch(() => {
      proxy.$modal.msgSuccess("复制失败");
    });
} else {
  // 创建text area
  const textArea = document.createElement("textarea");
  textArea.value = JSON.stringify(geometries);
  // 使text area不在viewport,同时设置不可见
  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();
  new Promise((resolve, reject) => {
    // 执行复制命令并移除文本框
    document.execCommand("copy") ? resolve() : reject(new Error("出错了"));
    textArea.remove();
  }).then(
    () => {
      proxy.$modal.msgSuccess("已复制");
    },
    () => {
      proxy.$modal.msgSuccess("复制失败");
    }
  );
}