为什么 \`navigator.clipboard.writeText\` 在 android 上由 alert() 处理时不将文本复制到剪贴板

新手上路,请多包涵

当尝试使用 navigator.clipboard.writeText() 只要我之后不显示警报,它就可以工作。我显示 alert() 的那一刻它就不再起作用了。

例如,这按预期工作正常

 function myFunction() {
  var copyText = document.getElementById("myInput");
  copyText.select();
  copyText.setSelectionRange(0, 99999);
  navigator.clipboard.writeText(copyText.value);
}
 <input type="text" value="Hello world" id="myInput" style="width:auto">
<button onclick="myFunction()">copy</button>

然而,这不起作用,它不会在控制台中抛出任何错误,并且在 PC 上的 chrome 上运行良好,但不适用于 Android。

 function myFunction()
{
  var copyText = document.getElementById("myInput");
  copyText.select();
  copyText.setSelectionRange(0, 99999);
  navigator.clipboard.writeText(copyText.value);
  alert("Successfully copied the text")
}
 <input type="text" value="Hello world" id="myInput"  style="width:auto" >
<button onclick="myFunction()" >copy</button>

任何人都知道发生了什么事?!。谢谢

原文由 Antony 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.1k
2 个回答

因为 navigator.clipboard.writeText 方法返回一个承诺,您的代码不会等待其结果。

如果您按如下所示更正代码,那么它应该没问题:

 function myFunction() {
    var copyText = document.getElementById("myInput");
    copyText.select();
    copyText.setSelectionRange(0, 99999);
    navigator.clipboard
      .writeText(copyText.value)
      .then(() => {
        alert("successfully copied");
      })
      .catch(() => {
        alert("something went wrong");
      });
}

有关 Promisenavigator.clipboard.writeText 方法的更多信息,请访问以下链接:

JavaScript.info 上的承诺

与 MDN 上的剪贴板交互

原文由 Agil Atakishiyev 发布,翻译遵循 CC BY-SA 4.0 许可协议

原因 navigator.clipboard.writetext 不起作用:

  1. 兼容性问题:此方法是在弃用 document.exec("copy") 方法后添加的。在 某些版本的浏览器 中,此方法将不起作用,您应该检查此方法是否可用。

  2. 文档未聚焦:如果您在没有任何用户交互的情况下向剪贴板写入内容。浏览器将阻止您的请求并在该方法的 Promise 中抛出错误。想象一个用户想要复制您从互联网加载的字符串 ( ajax )。如果这个 ajax 请求时间有点长,浏览器的焦点就会过期,我的经验是复制不了。

  3. 未授予权限:有时用户可能会通过编辑其隐私和安全设置来阻止自动复制到浏览器中的剪贴板。在进行复制之前,您应该检查写剪贴板的权限。但是 clipboard-write 权限会自动授予页面,当它们在活动选项卡中时。

  4. 异步问题:复制到剪贴板是一个异步操作,您应该等待您的代码完成工作。

  5. HTTP 网站:此功能仅在安全上下文 (HTTPS) 中可用,在某些或所有支持的浏览器中可用。

  6. Apple Safari 问题:Apple 的剪贴板 API 在写入剪贴板时主要期望 Promise 。因此,我们可以使用 PromiseClipboardItem 传递给 write 方法。我建议你使用 write 而不是 writeText

谈话很便宜,给我看 代码

 function copy(text) {
    return new Promise((resolve, reject) => {
        if (typeof navigator !== "undefined" && typeof navigator.clipboard !== "undefined" && navigator.permissions !== "undefined") {
            const type = "text/plain";
            const blob = new Blob([text], { type });
            const data = [new ClipboardItem({ [type]: blob })];
            navigator.permissions.query({name: "clipboard-write"}).then((permission) => {
                if (permission.state === "granted" || permission.state === "prompt") {
                    navigator.clipboard.write(data).then(resolve, reject).catch(reject);
                }
                else {
                    reject(new Error("Permission not granted!"));
                }
            });
        }
        else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
            var textarea = document.createElement("textarea");
            textarea.textContent = text;
            textarea.style.position = "fixed";
            textarea.style.width = '2em';
            textarea.style.height = '2em';
            textarea.style.padding = 0;
            textarea.style.border = 'none';
            textarea.style.outline = 'none';
            textarea.style.boxShadow = 'none';
            textarea.style.background = 'transparent';
            document.body.appendChild(textarea);
            textarea.focus();
            textarea.select();
            try {
                document.execCommand("copy");
                document.body.removeChild(textarea);
                resolve();
            }
            catch (e) {
                document.body.removeChild(textarea);
                reject(e);
            }
        }
        else {
            reject(new Error("None of copying methods are supported by this browser!"));
        }
    });

}

用法

 try {
    await copy("Hay yah!");
}
catch(e) {
    console.error(e);
}

重要说明:通过按钮和 onclick 事件测试它,而不是在控制台中。

原文由 Amir Fo 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题