JavaScript實(shí)現(xiàn)復(fù)制粘貼剪切功能三種方法
方式一:原生方式實(shí)現(xiàn)復(fù)制粘貼剪切(不推薦)
使用瀏覽器自帶的document.execCommand('copy')
實(shí)現(xiàn)復(fù)制,document.execCommand('paste')
實(shí)現(xiàn)粘貼,document.execCommand('cut')
實(shí)現(xiàn)剪切,這三個方法的返回值是布爾類型,用來判斷當(dāng)前瀏覽器中能夠使用這些方法,true表示方法能用,false表示方法不能用,目前因?yàn)?code>document.execCommand('paste')涉及到安全問題,考慮到安全原因, document.execCommand(‘paste’)操作已經(jīng)被禁止了。
補(bǔ)充說明下,目前官方已經(jīng)不推薦使用原生方式進(jìn)行復(fù)制粘貼操作了,這幾種方法隨時可能會被刪掉
代碼如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <input type="text" id="input" value="123" /> <button onclick="copy1()">復(fù)制(復(fù)制可編輯的標(biāo)簽中的內(nèi)容)</button> <button onclick="copy2('這是復(fù)制的內(nèi)容')">復(fù)制(將可編輯的標(biāo)簽隱藏)</button> <button onclick="cut()">剪切</button> <button onclick="paste()">粘貼</button> <input type="text" id="output"> <script> // 復(fù)制可編輯標(biāo)簽中的value值得內(nèi)容 function copy1() { const inputEle = document.querySelector("#input"); inputEle.select(); // 鼠標(biāo)選擇的內(nèi)容 document.execCommand("copy"); // 復(fù)制 } /** * 如果想使用 execCommand 方法,又不想頁面中出現(xiàn)可編輯區(qū)域,可以用下述辦法取巧 * @content 是要復(fù)制的內(nèi)容 */ function copy2(content) { const dom = document.createElement("input"); dom.value = content; document.body.appendChild(dom); dom.select(); document.execCommand("copy"); document.body.removeChild(dom); } // 剪切功能 function cut(){ console.log("cut"); document.execCommand("cut") } // 粘貼功能:注意,只會在光標(biāo)所在位置進(jìn)行粘貼 // function paste(){ // const pasteText = document.querySelector("#output") // pasteText.focus() // 讓光標(biāo)聚焦到output標(biāo)識的輸入框上 // document.execCommand("paste"); // 截至目前該方法涉及到安全問題已失效 // } </script> </body> </html>
使用execCommand命令存在以下缺陷:
(1)不夠靈活。只能操作input, textarea或具有contenteditable屬性的元素
(2)execCommand是同步操作,如果復(fù)制/粘貼大量數(shù)據(jù),頁面會出現(xiàn)卡頓。
(3)有些瀏覽器還會跳出提示框,要求用戶許可,這時在用戶做出選擇前,頁面會失去響應(yīng)。
(4)它只能將選中的內(nèi)容復(fù)制到剪貼板,無法向剪貼板任意寫入內(nèi)容
方式二:瀏覽器自帶clipboard API實(shí)現(xiàn)復(fù)制粘貼(推薦)
簡介
ClipboardAPI是下一代的剪貼板操作方法,比傳統(tǒng)的document.execCommand()
方法更加強(qiáng)大、更合理。
特點(diǎn)
(1)它的所有操作都是異步進(jìn)行的,返回promise對象,不糊造成頁面卡頓,
(2)它可以將任何內(nèi)容(例如圖片)放入到剪貼板。
(3)安全。通過navigator.clipboard
屬性返回Clipboard對象,所有操作都通過這個對象進(jìn)行,如果navigator.clipboard
屬性返回undefined
,就說明當(dāng)前瀏覽器不支持這個API。
1)有時候用戶可能會把敏感數(shù)據(jù)(比如密碼)放在剪貼板允許腳本任意讀取會產(chǎn)生風(fēng)險(xiǎn),而通過Clipboard對象進(jìn)行判斷,則很好的避免了這個風(fēng)險(xiǎn)。
2)此外,有些瀏覽器規(guī)定(例如Chrome),只有HTTPS協(xié)議(或者開發(fā)環(huán)境、本地環(huán)境下)的頁面才能使用這個API,由于從 Chrome 76 開始,Clipboard API 將不再被允許在非加密環(huán)境下(即純 HTTP)使用。這是因?yàn)樵?HTTP 環(huán)境下,網(wǎng)絡(luò)傳輸是明文的,容易被竊聽和篡改,因此會引入安全風(fēng)險(xiǎn)。
3)其次,復(fù)制權(quán)限是用戶默認(rèn)賦予的,而粘貼權(quán)限是需要用戶手動同意的,例如,在寫入剪貼板時腳本可以自動完成,但是讀取剪貼板時,瀏覽器會彈出一個對話框咨詢用戶是否同意讀取。
(4)有一點(diǎn)需要特別注意,腳本讀取的是當(dāng)前頁面的剪切板(注意我說的是瀏覽器中的剪貼板,而不是電腦操作系統(tǒng)自帶的剪貼板),這帶來一個問題,如果想把相關(guān)的代碼粘貼到開發(fā)者工具中直接運(yùn)行,可能會報(bào)錯,因?yàn)檫@時的當(dāng)前頁面是開發(fā)者工具的窗口,而不是網(wǎng)頁頁面。
例如:你把下面的代碼粘貼到開發(fā)者工具運(yùn)行就會報(bào)錯。
(async () => { const text = await navigator.clipboard.readText(); console.log(text); })();
因?yàn)樵诖a運(yùn)行的時候,開發(fā)者工具窗口是當(dāng)前頁,這個頁面不存在ClipboardAPI依賴的DOM接口。
解決辦法是將相關(guān)代碼放到setTimeout()里面延遲運(yùn)行,在調(diào)用函數(shù)之前快速點(diǎn)擊瀏覽器的頁面窗口,將其變成當(dāng)前頁。
setTimeout(async () => { const text = await navigator.clipboard.readText(); console.log(text); }, 2000);
clipboard對象及相關(guān)API
clipboard對象提供了四個方法用來讀寫剪貼板,他們都是異步方法,返回promise對象。
Clipboard.readText()
Clipboard.readText()
方法用來復(fù)制剪貼板(也就是粘貼功能)里面的文本數(shù)據(jù)。
該方法返回的是Promise對象,那么我這里提供兩種使用形式
- 形式一:pormise回調(diào)實(shí)現(xiàn)
// 普通方法 function paste() { navigator.clipboard // 創(chuàng)建clipboard對象 .readText() // 調(diào)用readText()方法 .then((clipText) => { // 成功回調(diào) console.log(clipText); // clipText是從剪貼板讀取到的內(nèi)容(也就是要粘貼的內(nèi)容) }) .catch((err) => console.log("粘貼失?。?,err)); // 失敗回調(diào) }
- 形式二:async函數(shù)
// async 函數(shù) async function paste(){ try{ // 創(chuàng)建clipboard對象并調(diào)用readText()方法讀取剪貼板上的內(nèi)容進(jìn)行返回 const text = await navigator.clipboard.readText() console.log("要粘貼的內(nèi)容為:",text); // 具體粘貼到哪你自己決定 }catch(err){ // catch捕獲處理報(bào)錯 console.log("粘貼失??!",err); } }
注意,如果用戶不允許使用這個API進(jìn)行粘貼操作,那么腳本就會報(bào)錯,那么我們就可以用catch()方法進(jìn)行處理報(bào)錯。
Clipboard.read()
Clipboard.read()
方法用于復(fù)制剪貼板(也就是粘貼功能)里面的數(shù)據(jù),可以是文本數(shù)據(jù),也可以是二進(jìn)制數(shù)據(jù)(比如圖片)。該方法需要用戶明確給予許可。
該方法返回一個 Promise 對象。一旦該對象的狀態(tài)變?yōu)?resolved,就可以獲得一個數(shù)組,每個數(shù)組成員都是 ClipboardItem 對象的實(shí)例。
下面我們簡單介紹下代碼中用到的幾個對象屬性和方法
遍歷通過Clipboard.read()
方法成功回調(diào)得到的數(shù)組對象,由此得到一個個的ClipboardItem
對象,表示一個單獨(dú)的剪貼項(xiàng),每個剪貼項(xiàng)都擁有ClipboardItem.types屬性
和ClipboardItem.getType()方法
。
1、ClipboardItem.types屬性
返回一個數(shù)組,里面的成員是該剪貼項(xiàng)可用的 MIME 類型,比如某個剪貼項(xiàng)可以用 HTML 格式粘貼,也可以用純文本格式粘貼,那么它就有兩個 MIME 類型(text/html和text/plain)。
2、ClipboardItem.getType(type)方法
用于讀取剪貼項(xiàng)的數(shù)據(jù),返回一個 Promise 對象。該方法接受剪貼項(xiàng)的 MIME 類型作為參數(shù),返回該類型的數(shù)據(jù),該參數(shù)是必需的,否則會報(bào)錯。
代碼示例如下:
- 形式一:promise回調(diào)實(shí)現(xiàn)
// 粘貼任何類型的數(shù)據(jù) function paste() { navigator.clipboard .read() // 調(diào)用read()方法從剪貼板讀取數(shù)據(jù)進(jìn)行粘貼操作 .then((clipboardItems) => { console.log(clipboardItems,"clipboardItems ========="); // clipboardItems是一個數(shù)組 for (const clipboardItem of clipboardItems) { console.log(clipboardItem, "clipboardItem ========="); // clipboardItem是一個實(shí)例對象 for (const type of clipboardItem.types) { // clipboardItem.types返回一個數(shù)組,存儲的是每一段剪貼板的mine數(shù)據(jù)類型 clipboardItem .getType(type) // 讀取接收到的mine類型作為參數(shù),返回該類型的數(shù)據(jù) .then((res) => console.log(res)) .catch((err) => console.log(err)); } } }) .catch((err) => { console.log(err.name,err.message) }); }
- 形式二:async函數(shù)+await實(shí)現(xiàn)
async function paste(){ try { const clipboardItems = await navigator.clipboard.read() for(const clipboardItem of clipboardItems){ for(const type of clipboardItem.types){ const result = await clipboardItem.getType(type) console.log(result); } } } catch (err) { console.log(err.name,err.message); } }
顯然使用第二種方式實(shí)現(xiàn)代碼更簡單。
Clipboard.writeText()
Clipboard.writeText()
方法用于將文本內(nèi)容寫入剪貼板(也就是復(fù)制功能),該方法同樣返回一個Promise對象。
代碼示例如下:
下面代碼功能是:通過點(diǎn)擊頁面,將數(shù)據(jù)復(fù)制到剪貼板。
document.body.addEventListener('click',async (e) => { await navigator.clipboard.writeText('Yo') // 參數(shù)是要寫入的文本 } )
當(dāng)然你可以通過點(diǎn)擊一個按鈕,一個標(biāo)簽等來觸發(fā)該復(fù)制操作。
Clipboard.write()
Clipboard.write()
方法用于將任意數(shù)據(jù)寫入剪貼板,可以是文本數(shù)據(jù),也可以是二進(jìn)制數(shù)據(jù)。
該方法接受一個 ClipboardItem 實(shí)例作為參數(shù),表示寫入剪貼板的數(shù)據(jù)。
- 代碼示例復(fù)制一個圖片類型
async function copy1() { try { // 圖片地址 const imgURL = "https://dummyimage.com/300.png"; // 獲取圖片 const data = await fetch(imgURL); // 將圖片轉(zhuǎn)為blob類型 const blob = await data.blob(); // 將數(shù)據(jù)寫入(復(fù)制)到剪貼板 await navigator.clipboard.write([ // 創(chuàng)建Clipboard實(shí)例對象,對象的鍵名是數(shù)據(jù)的 MIME 類型,鍵值就是數(shù)據(jù)本身 new ClipboardItem({ [blob.type]: blob, }), ]); console.log("Image copied."); } catch (err) { console.error(err.name, err.message); } }
ClipboardItem()
是瀏覽器原生提供的構(gòu)造函數(shù),用來生成ClipboardItem實(shí)例,它接收一個對象作為參數(shù),該對象的鍵名是數(shù)據(jù)的 MIME 類型,鍵值就是數(shù)據(jù)本身。
注意,Chrome 瀏覽器目前只支持寫入 PNG 格式的圖片。
此外,write()方法還可以將用一個剪貼項(xiàng)的多種格式的值寫入到剪貼板,一種是文本數(shù)據(jù),一種是二進(jìn)制數(shù)據(jù),供不同的場合粘貼使用。
function copy() { const image = await fetch('kitten.png'); // 獲取圖片類型的數(shù)據(jù) const blob = await image.blob(); // 將圖片轉(zhuǎn)為blob對象 const text = new Blob(['Cute sleeping kitten'], {type: 'text/plain'}); // 獲取文字類型的數(shù)據(jù)并轉(zhuǎn)為blob實(shí)例對象 const item = new ClipboardItem({ 'text/plain': text, [blob.type]: image }); await navigator.clipboard.write([item]); }
就是剪貼板中的剪貼項(xiàng)有兩種類型的數(shù)據(jù),在你要圖片時,我就將剪貼板中的數(shù)據(jù)用圖片的形式給你粘貼使用,要用文字時,就粘貼文字給你。
方式三:clipboard.js插件庫實(shí)現(xiàn)復(fù)制剪切(推薦)
它是一個不需要Flash,就能實(shí)現(xiàn)文本復(fù)制或者剪切到剪切板的輕量級插件(注意沒有粘貼哦)
官網(wǎng):clipboard.js
安裝引入
# node安裝 npm install clipboard --save
<!-- html文件中可以使用CDN引入 --> <script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js"></script>
// js文件中可以通過ES6語法的import或者commonjs進(jìn)行引入或者使用其他引入方式
這個庫同時依賴于Selection
和execCommand
api。所有瀏覽器都支持第一個,而以下瀏覽器支持第二個。chrome42+,Edge12+,F(xiàn)irefox41+,IE9+,Opera2+,Safari0+
基本使用
總共有兩步,第一步在指定的html標(biāo)簽中使用指定屬性進(jìn)行綁定,第二部創(chuàng)建Clipboard實(shí)例對象調(diào)用相關(guān)的event事件,操作如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <!-- 引入clipboard.js --> <script src="https://cdn.bootcdn.net/ajax/libs/clipboard.js/2.0.11/clipboard.js"></script> <title>Document</title> </head> <body> <div> <!-- Target --> <input type="text" id="foo" value="要復(fù)制的內(nèi)容" /> <!-- Trigger --> <button class="btn" data-clipboard-target="#foo" data-clipboard-action="copy">復(fù)制</button> <!-- 有兩個屬性值: data-clipboard-target:取值是一個選擇器對象,用來綁定要復(fù)制的標(biāo)簽,復(fù)制其內(nèi)容 data-clipboard-action:用來決定是復(fù)制還是粘貼,有兩個取值:copy和cut --> </div> <script> // 創(chuàng)建一個實(shí)例對象,參數(shù)是一個選擇器,綁定的是觸發(fā)復(fù)制/剪切事件的標(biāo)簽 var clipboard = new ClipboardJS(".btn"); // 成功回調(diào) clipboard.on("success", function (e) { console.info("Action:", e.action); // 操作:copy或者cut console.info("Text:", e.text); // 復(fù)制/剪切的內(nèi)容 console.info("Trigger:", e.trigger); // 觸發(fā)對象 e.clearSelection(); }); // 失敗回調(diào) clipboard.on("error", function (e) { console.error("Action:", e.action); // 操作:copy或者cut console.error("Trigger:", e.trigger); // 觸發(fā)對象 }); </script> </body> </html>
可以通過ClipboardJS.isSupported()
方法判斷瀏覽器是否可以使用這個庫
進(jìn)階使用
new ClipboardJS("選擇器",{...})
方法,第二個參數(shù)是一個對象,你可以往里面?zhèn)魅牖卣{(diào)函數(shù),如下
(1)通過函數(shù)返回要綁定的節(jié)點(diǎn)target
new ClipboardJS('.btn', { target: function(trigger) { return trigger.nextElementSibling; } });
(2)通過函數(shù)設(shè)置要復(fù)制的文本內(nèi)容text
new ClipboardJS('.btn', { text: function(trigger) { return trigger.getAttribute('aria-label'); } });
(3)在Bootstrap Modals 中或與任何其他更改焦點(diǎn)的庫一起使用時,將焦點(diǎn)元素設(shè)置為 container 值
new ClipboardJS('.btn', { container: document.getElementById('modal') });
(4)銷毀復(fù)制粘貼的實(shí)例對象(如果在單頁應(yīng)用中使用時,要更精確地管理DOM的生命周期,可以使用以下方法清除創(chuàng)建的事件對象)
var clipboard = new ClipboardJS('.btn'); clipboard.destroy();
可以看到這個插件庫基本的功能是復(fù)制和剪切,沒有涉及到粘貼操作,所以,通常會和瀏覽器自帶clipboardAPI配合使用實(shí)現(xiàn)復(fù)制粘貼操作。
補(bǔ)充:復(fù)制粘貼操作攔截
主要用到了copy和paste事件
copy
例如:復(fù)制操作時,將用戶放入到剪貼板中的文本轉(zhuǎn)為大寫
const source = document.querySelector('.source'); source.addEventListener('copy', (event) => { const selection = document.getSelection(); event.clipboardData.setData('text/plain', selection.toString().toUpperCase()); event.preventDefault(); });
上面示例中,事件對象的clipboardData屬性包含了剪貼板數(shù)據(jù)。它是一個對象,有以下屬性和方法。
Event.clipboardData.setData(type, data)
:修改剪貼板數(shù)據(jù),需要指定數(shù)據(jù)類型。Event.clipboardData.getData(type)
:獲取剪貼板數(shù)據(jù),需要指定數(shù)據(jù)類型Event.clipboardData.clearData([type])
:清除剪貼板數(shù)據(jù),可以指定數(shù)據(jù)類型。如果不指定類型,將清除所有類型的數(shù)據(jù)。Event.clipboardData.items
:一個類似數(shù)組的對象,包含了所有剪貼項(xiàng),不過通常只有一個剪貼項(xiàng)。
例如:攔截用戶的復(fù)制操作,將指定內(nèi)容放入剪貼板
onst clipboardItems = []; document.addEventListener('copy', async (e) => { e.preventDefault(); // 先使用該方法組織默認(rèn)事件,然后由腳本接管復(fù)制操作 try { let clipboardItems = []; for (const item of e.clipboardData.items) { if (!item.type.startsWith('image/')) { continue; } clipboardItems.push( new ClipboardItem({ [item.type]: item, }) ); await navigator.clipboard.write(clipboardItems); console.log('Image copied.'); } } catch (err) { console.error(err.name, err.message); } });
paste
用戶使用剪貼板數(shù)據(jù),進(jìn)行粘貼操作時,會觸發(fā)paste事件
document.addEventListener('paste', async (e) => { e.preventDefault(); const text = await navigator.clipboard.readText(); console.log('Pasted text: ', text); });
總結(jié)
到此這篇關(guān)于JavaScript實(shí)現(xiàn)復(fù)制粘貼剪切功能的文章就介紹到這了,更多相關(guān)JS復(fù)制粘貼剪切功能內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript獲取網(wǎng)頁中第一個鏈接ID的方法
這篇文章主要介紹了JavaScript獲取網(wǎng)頁中第一個鏈接ID的方法,涉及javascript中document.links方法的使用,需要的朋友可以參考下2015-04-04使用JavaScript實(shí)現(xiàn)獲取頁面滾動位置
這篇文章主要為大家詳細(xì)介紹了在JavaScript中如何獲取水平和垂直的滾動位置,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下2024-12-12js模擬jquery的slide和fadeIn和fadeOut功能
以前用過jquery的slideUp,slideDown,等許多很不錯的方法,感覺很容易就能實(shí)現(xiàn)頁面元素的動畫效果!2010-07-07如何根據(jù)url?批量下載二維碼實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了如何根據(jù)url批量下載二維碼實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05深入理解JavaScript系列(26):設(shè)計(jì)模式之構(gòu)造函數(shù)模式詳解
這篇文章主要介紹了深入理解JavaScript系列(26):設(shè)計(jì)模式之構(gòu)造函數(shù)模式詳解,本文講解了基本用法、構(gòu)造函數(shù)與原型、只能用new嗎?、強(qiáng)制使用new、原始包裝函數(shù)等內(nèi)容,需要的朋友可以參考下2015-03-03JavaScript設(shè)計(jì)模式之建造者模式實(shí)例教程
這篇文章主要介紹了JavaScript設(shè)計(jì)模式之建造者模式,結(jié)合實(shí)例形式分析了設(shè)計(jì)模式中建造者模式的概念、功能及JavaScript實(shí)現(xiàn)與使用建造者模式的相關(guān)操作技巧,需要的朋友可以參考下2018-07-07