現在有許多第三方外掛程式能夠實現copy 功能,但如果讓我們自己做,我們知道如何實現嗎?
這篇文章介紹三種實作方案。
使用Async Clipboard API
這種方式使用起來最簡單,但相容性不太好,而且要求比較多。
範例程式碼:
const promise = navigator.clipboard.writeText(newClipText);
需要注意,方法的回傳值是個Promise。並且使用此方法時,頁面必須處於focus 狀態,否則會報錯。
使用Document.execCommand
此方法雖然警告被廢棄,不再屬於web 標準,但歷史因素較多,相信瀏覽器還會支援很久。
<p id="content">123456</p> <button id="copyButton">複製</button>
複製DOM 元素的時候,需要額外使用到selection API 和Range API。
developer.mozilla.org/en-US/docs/…
developer.mozilla.org/en-US/docs/…
範例程式碼:
const copyButton = document.getElementById('copyButton'); const content = document.getElementById('content'); copyButton.addEventListener('click', function () { const selection = window.getSelection(); const range = document.createRange(); // 設定選取內容range.selectNodeContents(content); // 清空選取內容selection.removeAllRanges(); // 新增選取內容selection.addRange(range); document.execCommand('copy'); });
selection 需要先清空再加入range。
這裡會有一個細節問題,點擊複製按鈕之後,被複製的內容處於選取狀態,有些突兀。
解決方式是複製完成之後呼叫selection.removeAllRanges()
清空選取內容即可。
再考慮一種情況,使用者在複製之前就選取了頁面的部分內容。複製完成之後,除了清空選取的複製內容,還需要還原使用者在複製之前就選取的內容。
實作程式碼如下:
const copyButton = document.getElementById('copyButton'); const content = document.getElementById('content'); copyButton.addEventListener('click', function () { const selection = window.getSelection(); const range = document.createRange(); // 快取使用者選取的內容const currentRange = selection.rangeCount === 0 ? null : selection.getRangeAt(0); // 設定文件片段range.selectNodeContents(content); // 清空選取內容selection.removeAllRanges(); // 將文件片段設定為選取內容selection.addRange(range); try { // 複製到剪貼簿document.execCommand('copy'); } catch (err) { // 提示複製失敗} finally { selection.removeAllRanges(); if (currentRange) { // 還原使用者選取內容selection.addRange(currentRange); } } });
先快取使用者選取的內容,複製完成之後,再還原。
使用input 元素物件的select
方法即可選取內容,無需建立range 片段設定選取內容。
範例程式碼:
const copyButton = document.getElementById('copyButton'); const inputEl = document.getElementById('input'); copyButton.addEventListener('click', function () { const selection = window.getSelection(); const currentRange = selection.rangeCount === 0 ? null : selection.getRangeAt(0); // 選取input 內容inputEl.select(); // 複製到剪貼簿try { document.execCommand('copy'); } catch (err) { // 提示複製失敗// 。 。 。 } finally { selection.removeAllRanges(); if (currentRange) { // 還原使用者選取內容selection.addRange(currentRange); } } });
點選複製按鈕,同樣不會移除先前選取的內容。
w3c.github.io/clipboard-a…
引用上面連結內的一段程式碼作為範例:
// Overwrite what is being copied to the clipboard. document.addEventListener('copy', function (e) { // e.clipboardData is initially empty, but we can set it to the // data that we want copied onto the clipboard. e.clipboardData.setData('text/plain', '西炒蛋'); // This is necessary to prevent the current document selection from // being written to the clipboard. e.preventDefault(); });
在頁面複製任何內容,貼上輸出的內容都會是「西炒蛋」。