為什麼在安卓裝置上,如果在`navigator.clipboard.writeText`之前有`alert()`,它就無法成功複製文字到剪貼簿?
P粉386318086
P粉386318086 2023-08-22 19:21:37
0
2
850
<p>當嘗試在安卓的Chrome瀏覽器上使用<code>navigator.clipboard.writeText()</code>複製一些文字時,只要我之後不顯示警告框,它就能正常工作。一旦我顯示了一個alert(),它就不再工作了。 </p> <p>例如,下面的程式碼按預期運作正常:</p> <p><br /></p> <pre class="brush:js;toolbar:false;">function myFunction() { var copyText = document.getElementById("myInput"); copyText.select(); copyText.setSelectionRange(0, 99999); navigator.clipboard.writeText(copyText.value); }</pre> <pre class="brush:html;toolbar:false;"><input type="text" value="Hello world" id="myInput" style="width:auto"> <button onclick="myFunction()">copy</button></pre> <p><br /></p> <p>然而下面的程式碼不起作用,在控制台中不會拋出任何錯誤,並且在PC上的Chrome瀏覽器上正常工作,但在安卓上不行。 </p> <p><br /></p> <pre class="brush:js;toolbar:false;">function myFunction() { var copyText = document.getElementById("myInput"); copyText.select(); copyText.setSelectionRange(0, 99999); navigator.clipboard.writeText(copyText.value); alert("成功複製了文本") }</pre> <pre class="brush:html;toolbar:false;"><input type="text" value="Hello world" id="myInput" style="width:auto" > <button onclick="myFunction()" >copy</button></pre> <p><br /></p> <p>有人知道發生了什麼事嗎?謝謝。 </p>
P粉386318086
P粉386318086

全部回覆(2)
P粉354948724

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

  1. 相容性問題:在廢棄了 document.exec("copy") 方法後,此方法是後來新增的。在 某些瀏覽器版本 中,此方法將無法運作,您應該檢查此方法是否可用。

  2. 文件未聚焦:如果您在沒有任何使用者互動的情況下將內容寫入剪貼簿,瀏覽器將阻止您的請求,並在此方法的Promise 中拋出錯誤。想像一下,使用者想要複製一個您從網路上載入的字串(ajax)。如果此 ajax 請求花費了一點時間,瀏覽器的焦點將會過期,我的經驗是無法完成複製。

  3. 未授權的權限:有時使用者可能會透過編輯其隱私和安全性設定來阻止瀏覽器自動複製到剪貼簿。在進行複製之前,請檢查寫入剪貼簿的權限。但是,當頁面處於活動標籤時,clipboard-write 權限會自動授予頁面。

  4. 非同步問題:複製到剪貼簿是一個非同步操作,您應該等待您的程式碼完成工作。

  5. HTTP 網站:此功能僅在安全性上下文(HTTPS)中可用,在某些或所有支援的瀏覽器中。

  6. Apple Safari 問題:蘋果的 Clipboard API 大多數情況下期望一個 Promise 在寫入剪貼簿時。因此,我們可以使用 ClipboardItem 將一個 Promise 傳遞給 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 事件進行測試,而不是在控制台中。

P粉759457420

因為navigator.clipboard.writeText方法回傳一個Promise,而你的程式碼沒有等待它的結果。

如果你按照下面的程式碼修正,應該就沒問題了:

function myFunction() {
    var copyText = document.getElementById("myInput");
    copyText.select();
    copyText.setSelectionRange(0, 99999);
    navigator.clipboard
      .writeText(copyText.value)
      .then(() => {
        alert("成功复制");
      })
      .catch(() => {
        alert("出了点问题");
      });
}

有關Promisenavigator.clipboard.writeText方法的更多信息,請訪問以下連結:
JavaScript.info上的Promise
MDN上與剪貼簿互動

#
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板