JavaScript實現(xiàn)復(fù)制粘貼剪切功能三種方法
方式一:原生方式實現(xiàn)復(fù)制粘貼剪切(不推薦)
使用瀏覽器自帶的document.execCommand('copy')實現(xiàn)復(fù)制,document.execCommand('paste')實現(xiàn)粘貼,document.execCommand('cut')實現(xiàn)剪切,這三個方法的返回值是布爾類型,用來判斷當(dāng)前瀏覽器中能夠使用這些方法,true表示方法能用,false表示方法不能用,目前因為document.execCommand('paste')涉及到安全問題,考慮到安全原因, document.execCommand(‘paste’)操作已經(jīng)被禁止了。
補充說明下,目前官方已經(jīng)不推薦使用原生方式進行復(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)所在位置進行粘貼
// 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實現(xiàn)復(fù)制粘貼(推薦)
簡介
ClipboardAPI是下一代的剪貼板操作方法,比傳統(tǒng)的document.execCommand()方法更加強大、更合理。
特點
(1)它的所有操作都是異步進行的,返回promise對象,不糊造成頁面卡頓,
(2)它可以將任何內(nèi)容(例如圖片)放入到剪貼板。
(3)安全。通過navigator.clipboard屬性返回Clipboard對象,所有操作都通過這個對象進行,如果navigator.clipboard屬性返回undefined,就說明當(dāng)前瀏覽器不支持這個API。
1)有時候用戶可能會把敏感數(shù)據(jù)(比如密碼)放在剪貼板允許腳本任意讀取會產(chǎn)生風(fēng)險,而通過Clipboard對象進行判斷,則很好的避免了這個風(fēng)險。
2)此外,有些瀏覽器規(guī)定(例如Chrome),只有HTTPS協(xié)議(或者開發(fā)環(huán)境、本地環(huán)境下)的頁面才能使用這個API,由于從 Chrome 76 開始,Clipboard API 將不再被允許在非加密環(huán)境下(即純 HTTP)使用。這是因為在 HTTP 環(huán)境下,網(wǎng)絡(luò)傳輸是明文的,容易被竊聽和篡改,因此會引入安全風(fēng)險。
3)其次,復(fù)制權(quán)限是用戶默認(rèn)賦予的,而粘貼權(quán)限是需要用戶手動同意的,例如,在寫入剪貼板時腳本可以自動完成,但是讀取剪貼板時,瀏覽器會彈出一個對話框咨詢用戶是否同意讀取。

(4)有一點需要特別注意,腳本讀取的是當(dāng)前頁面的剪切板(注意我說的是瀏覽器中的剪貼板,而不是電腦操作系統(tǒng)自帶的剪貼板),這帶來一個問題,如果想把相關(guān)的代碼粘貼到開發(fā)者工具中直接運行,可能會報錯,因為這時的當(dāng)前頁面是開發(fā)者工具的窗口,而不是網(wǎng)頁頁面。
例如:你把下面的代碼粘貼到開發(fā)者工具運行就會報錯。
(async () => {
const text = await navigator.clipboard.readText();
console.log(text);
})();
因為在代碼運行的時候,開發(fā)者工具窗口是當(dāng)前頁,這個頁面不存在ClipboardAPI依賴的DOM接口。
解決辦法是將相關(guān)代碼放到setTimeout()里面延遲運行,在調(diào)用函數(shù)之前快速點擊瀏覽器的頁面窗口,將其變成當(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)實現(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)容進行返回
const text = await navigator.clipboard.readText()
console.log("要粘貼的內(nèi)容為:",text); // 具體粘貼到哪你自己決定
}catch(err){
// catch捕獲處理報錯
console.log("粘貼失??!",err);
}
}
注意,如果用戶不允許使用這個API進行粘貼操作,那么腳本就會報錯,那么我們就可以用catch()方法進行處理報錯。
Clipboard.read()
Clipboard.read()方法用于復(fù)制剪貼板(也就是粘貼功能)里面的數(shù)據(jù),可以是文本數(shù)據(jù),也可以是二進制數(shù)據(jù)(比如圖片)。該方法需要用戶明確給予許可。
該方法返回一個 Promise 對象。一旦該對象的狀態(tài)變?yōu)?resolved,就可以獲得一個數(shù)組,每個數(shù)組成員都是 ClipboardItem 對象的實例。
下面我們簡單介紹下代碼中用到的幾個對象屬性和方法
遍歷通過Clipboard.read()方法成功回調(diào)得到的數(shù)組對象,由此得到一個個的ClipboardItem 對象,表示一個單獨的剪貼項,每個剪貼項都擁有ClipboardItem.types屬性和ClipboardItem.getType()方法。
1、ClipboardItem.types屬性返回一個數(shù)組,里面的成員是該剪貼項可用的 MIME 類型,比如某個剪貼項可以用 HTML 格式粘貼,也可以用純文本格式粘貼,那么它就有兩個 MIME 類型(text/html和text/plain)。
2、ClipboardItem.getType(type)方法用于讀取剪貼項的數(shù)據(jù),返回一個 Promise 對象。該方法接受剪貼項的 MIME 類型作為參數(shù),返回該類型的數(shù)據(jù),該參數(shù)是必需的,否則會報錯。
代碼示例如下:
- 形式一:promise回調(diào)實現(xiàn)
// 粘貼任何類型的數(shù)據(jù)
function paste() {
navigator.clipboard
.read() // 調(diào)用read()方法從剪貼板讀取數(shù)據(jù)進行粘貼操作
.then((clipboardItems) => {
console.log(clipboardItems,"clipboardItems =========");
// clipboardItems是一個數(shù)組
for (const clipboardItem of clipboardItems) {
console.log(clipboardItem, "clipboardItem ========="); // clipboardItem是一個實例對象
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實現(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);
}
}
顯然使用第二種方式實現(xiàn)代碼更簡單。
Clipboard.writeText()
Clipboard.writeText()方法用于將文本內(nèi)容寫入剪貼板(也就是復(fù)制功能),該方法同樣返回一個Promise對象。
代碼示例如下:
下面代碼功能是:通過點擊頁面,將數(shù)據(jù)復(fù)制到剪貼板。
document.body.addEventListener('click',async (e) => {
await navigator.clipboard.writeText('Yo') // 參數(shù)是要寫入的文本
}
)
當(dāng)然你可以通過點擊一個按鈕,一個標(biāo)簽等來觸發(fā)該復(fù)制操作。
Clipboard.write()
Clipboard.write()方法用于將任意數(shù)據(jù)寫入剪貼板,可以是文本數(shù)據(jù),也可以是二進制數(shù)據(jù)。
該方法接受一個 ClipboardItem 實例作為參數(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ù)據(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ù)據(jù)的 MIME 類型,鍵值就是數(shù)據(jù)本身。
注意,Chrome 瀏覽器目前只支持寫入 PNG 格式的圖片。
此外,write()方法還可以將用一個剪貼項的多種格式的值寫入到剪貼板,一種是文本數(shù)據(jù),一種是二進制數(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實例對象
const item = new ClipboardItem({
'text/plain': text,
[blob.type]: image
});
await navigator.clipboard.write([item]);
}
就是剪貼板中的剪貼項有兩種類型的數(shù)據(jù),在你要圖片時,我就將剪貼板中的數(shù)據(jù)用圖片的形式給你粘貼使用,要用文字時,就粘貼文字給你。
方式三:clipboard.js插件庫實現(xiàn)復(fù)制剪切(推薦)
它是一個不需要Flash,就能實現(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進行引入或者使用其他引入方式
這個庫同時依賴于Selection和execCommand api。所有瀏覽器都支持第一個,而以下瀏覽器支持第二個。chrome42+,Edge12+,F(xiàn)irefox41+,IE9+,Opera2+,Safari0+
基本使用
總共有兩步,第一步在指定的html標(biāo)簽中使用指定屬性進行綁定,第二部創(chuàng)建Clipboard實例對象調(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ù)是一個選擇器,綁定的是觸發(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()方法判斷瀏覽器是否可以使用這個庫
進階使用
new ClipboardJS("選擇器",{...})方法,第二個參數(shù)是一個對象,你可以往里面?zhèn)魅牖卣{(diào)函數(shù),如下
(1)通過函數(shù)返回要綁定的節(jié)點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 中或與任何其他更改焦點的庫一起使用時,將焦點元素設(shè)置為 container 值
new ClipboardJS('.btn', {
container: document.getElementById('modal')
});
(4)銷毀復(fù)制粘貼的實例對象(如果在單頁應(yīng)用中使用時,要更精確地管理DOM的生命周期,可以使用以下方法清除創(chuàng)建的事件對象)
var clipboard = new ClipboardJS('.btn');
clipboard.destroy();
可以看到這個插件庫基本的功能是復(fù)制和剪切,沒有涉及到粘貼操作,所以,通常會和瀏覽器自帶clipboardAPI配合使用實現(xiàn)復(fù)制粘貼操作。
補充:復(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ù)組的對象,包含了所有剪貼項,不過通常只有一個剪貼項。
例如:攔截用戶的復(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ù),進行粘貼操作時,會觸發(fā)paste事件
document.addEventListener('paste', async (e) => {
e.preventDefault();
const text = await navigator.clipboard.readText();
console.log('Pasted text: ', text);
});總結(jié)
到此這篇關(guān)于JavaScript實現(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
js模擬jquery的slide和fadeIn和fadeOut功能
以前用過jquery的slideUp,slideDown,等許多很不錯的方法,感覺很容易就能實現(xiàn)頁面元素的動畫效果!2010-07-07
深入理解JavaScript系列(26):設(shè)計模式之構(gòu)造函數(shù)模式詳解
這篇文章主要介紹了深入理解JavaScript系列(26):設(shè)計模式之構(gòu)造函數(shù)模式詳解,本文講解了基本用法、構(gòu)造函數(shù)與原型、只能用new嗎?、強制使用new、原始包裝函數(shù)等內(nèi)容,需要的朋友可以參考下2015-03-03

