如果在 android 上通过alert()处理,为什么`navigator.clipboard.writeText`不会将文本复制到剪贴板

Ant*_*ony 32 html javascript

当尝试在 Android 版 chrome 上复制一些文本时,navigator.clipboard.writeText()只要我之后不显示警报,它就可以工作。当我显示alert()时,它就不再起作用了。

例如,这按预期工作正常

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

然而这不起作用,它不会在控制台中抛出任何错误,并且在 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")
}
Run Code Online (Sandbox Code Playgroud)
<input type="text" value="Hello world" id="myInput"  style="width:auto" >
<button onclick="myFunction()" >copy</button>
Run Code Online (Sandbox Code Playgroud)

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

小智 63

Because the navigator.clipboard.writeText method returns a promise and your code does not wait for its result.

If you correct code as shown below then it should be fine:

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");
      });
}
Run Code Online (Sandbox Code Playgroud)

For further information about Promise and the navigator.clipboard.writeText method, please visit the following links:
Promise on JavaScript.info
Interact with the clipboard on MDN


Ami*_*ati 21

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

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

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

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

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

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

  6. Apple Safari 问题Promise:Apple 的剪贴板 API在写入剪贴板时大多需要 a 。Promise所以我们可以将using传递ClipboardItem给该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!"));
        }
    });
    
}
Run Code Online (Sandbox Code Playgroud)

用法

try {
    await copy("Hay yah!");
}
catch(e) {
    console.error(e);
}
Run Code Online (Sandbox Code Playgroud)

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

  • 非常好的、彻底的回答,阿米尔。做得好。 (2认同)