JavaScript實現點擊復制功能具體代碼(JS訪問剪貼板相關)
一、具體代碼
網頁前端開發(fā)中有時會出現這樣的場景:讓用戶點擊某個按鈕,然后就能直接復制對應的文本內容,讓用戶可以將文本內容粘貼到想要粘貼的地方,常用于分享功能模塊中。如果想要實現這種效果就需要我們去訪問用戶的剪貼板,然后把想要復制的內容寫入其中即可,本文主要講解兩種解決方案: document.execCommand() 和 Clipboard 。
先上代碼:
?為了同時兼容新舊瀏覽器(IE!),我們一般采取下面的方式:
// 復制文本內容
function copyContent (content) {
// 復制結果
let copyResult = true
// 設置想要復制的文本內容
const text = content || '讓我們一起快樂的敲代碼吧~';
// 判斷是否支持clipboard方式
if (!!window.navigator.clipboard) {
// 利用clipboard將文本寫入剪貼板(這是一個異步promise)
window.navigator.clipboard.writeText(text).then((res) => {
console.log('復制成功');
// 返回復制操作的最終結果
return copyResult;
}).catch((err) => {
copyResult = false
console.log('復制失敗', err);
// 返回復制操作的最終結果
return copyResult;
})
} else {
// 不支持clipboard方式 則采用document.execCommand()方式
// 創(chuàng)建一個input元素
let inputDom = document.createElement('textarea');
// 設置為只讀 防止移動端手機上彈出軟鍵盤
inputDom.setAttribute('readonly', 'readonly');
// 給input元素賦值
inputDom.value = text;
// 將創(chuàng)建的input添加到body
document.body.appendChild(inputDom);
// 選中input元素的內容
inputDom.select();
// 執(zhí)行瀏覽器復制命令
// 復制命令會將當前選中的內容復制到剪切板中(這里就是創(chuàng)建的input標簽中的內容)
// Input要在正常的編輯狀態(tài)下原生復制方法才會生效
const result = document.execCommand('copy')
// 判斷是否復制成功
if (result) {
console.log('復制成功');
} else {
console.log('復制失敗');
copyResult = false
}
// 復制操作后再將構造的標簽 移除
document.body.removeChild(inputDom);
// 返回復制操作的最終結果
return copyResult;
}
}二、剪貼板
? 剪貼板是用于短期數據存儲或者轉移的數據緩存區(qū),數據轉移可以發(fā)生在不同的文檔或應用程序之間。剪貼板常常實現為一個匿名的、臨時的數據緩存,有時也叫做粘貼緩存,可由絕大部分位于已定義應用程序接口的環(huán)境中的程序訪問。
三、Clipboard
1、簡介
? Clipboard API 提供了響應剪貼板命令和異步讀寫系統(tǒng)剪貼板的能力,該API是用來取代 document.execCommand() 這種剪貼板訪問方式的。但是該API需要通過 PerMissions API獲取用戶授予的權限( "clipboard-read" 或 "clipboard-write" )之后,才能訪問剪貼板,如果用戶拒絕授予相應權限,則無法訪問剪貼板,調用 Clipboard 對象的方法就會失敗。而且該API僅在一些安全上下文環(huán)境中可用(HTTPS、localhost、127.0.0.1等),我們可以通過 window.isSecureContext 的返回值來判斷當前環(huán)境是否為安全上下文環(huán)境。

? 我們可以通過 window.navigator.permissions.query({name: "clipboard-read"}) 和 window.navigator.permissions.query({name: "clipboard-write"}) 來判斷當前網頁是否擁有讀寫剪貼板的權限(Firefox不支持?。?。
? 該API在 Window.navigator 接口上添加了只讀屬性 clipboard ,該屬性返回一個可以讀寫剪切板內容的 Clipboard 對象,我們前端大多是通過 window.navigator.clipboard 來訪問剪貼板。
? 由于該API是一個較新的API,而且涉及的安全問題和技術復雜性太多,所以瀏覽器兼容性相對差一點(不支持IE):
瀏覽器兼容性(Navigator.clipboard):

2、Clipboard
? 該接口實現了 Clipboard API,用于讀寫系統(tǒng)剪貼板上的文本和數據的接口,前端規(guī)范稱其為異步剪貼板API(Async Clipboard API),因為該API下的所有方法都是異步的,它們會返回一個 Promise 對象,操作成功后調用 resolve() ,操作失敗后調用 reject() 。
相關方法:
① read()
? 該方法用于從系統(tǒng)剪貼板中讀取任意數據的副本(文本、圖片等),返回一個 Promise 對象,在經過異步數據檢索之后, Promise 返回一個包含相關數據的 ClipboardItem 對象的數組,該數組含有兩個數據對象,第一個對象中僅包含剪貼板中的文本數據,第二個對象中包含剪貼板中的所有內容數據。
? 該方法必須在網頁獲取焦點時,才能正常調用,否則會報錯。而且該方法不能在JS中直接調用,只能在處理用戶行為(點擊等交互行為)時才能正常調用,否則會報錯。
? 如果系統(tǒng)剪貼板中的內容是復制的系統(tǒng)本地的文件,則通過該方法只能訪問到文件名,而無法訪問到文件本身的內容。如果我們是復制的系統(tǒng)本地文件中的內容,并包含文本和圖片,則該方法能正常獲取到文本信息,但圖片無法被獲取到。
② readText()
? 該方法從系統(tǒng)剪貼板讀取中文本數據的副本,返回一個 Promise 對象,在經過異步數據檢索之后, Promise 返回一個包含相關文本數據的 String 字符串數據。
? 該方法必須在網頁獲取焦點時,才能正常調用,否則會報錯。但是與 read() 不同的是,該方法可以在JS中直接調用,不需要等待用戶行為。
? 如果系統(tǒng)剪貼板中的內容是復制的系統(tǒng)本地的文件,則通過該方法可以訪問到文件名。如果我們是復制的系統(tǒng)本地文件中的內容,并包含文本和圖片,則該方法只能獲取到其中文本信息。
案例代碼:
<button onclick="clickRead()">點擊訪問剪貼板</button>
<p>我想調用Clipboard API來讀取剪貼板信息</p>
<p>我想2342342342432</p>
<img src="./image/img.png" alt="">
<div>23423423422</div>
<script>
// 在剛進入頁面時,先嘗試獲取剪貼板的內容
window.navigator.clipboard.read().then((res) => {
console.log('read--res-----', res);
}).catch((err) => {
console.log('read--err-----', err);
})
// 在剛進入頁面時,先嘗試獲取剪貼板的文本內容
window.navigator.clipboard.readText().then((res) => {
console.log('readText--res-----', res);
}).catch((err) => {
console.log('readText--err-----', err);
})
// 用戶點擊按鈕事件
function clickRead () {
// 再次嘗試獲取剪貼板的內容 promise異步操作
window.navigator.clipboard.read().then((res) => {
console.log('用戶點擊-read--res-----', res);
res[0].types.forEach((type, index) => {
// 通過getType讀取剪貼板中對應的數據內容 并返回相應blob對象
res[0].getType(type).then(res => {
console.log('blob--', res);
let reader = new FileReader();
// 為了方便查看 將bolb轉為base64 (異步操作)
reader.readAsDataURL(res);
// 轉換成功
reader.onload = () => {
if (index === 0) {
console.log('用戶剪貼板中的所有文本內容轉換成的base64--', reader.result);
} else
if (index === 1) {
console.log('用戶剪貼板中的所有數據內容內容轉換成的base64--', reader.result);
}
};
});
})
}).catch((err) => {
// 讀取失敗的情況
console.log('用戶點擊-read--err-----', err);
})
// 在用戶點擊事件中 再次嘗試獲取剪貼板的文本內容
window.navigator.clipboard.readText().then((res) => {
// 讀取成功的情況
console.log('用戶點擊-readText--res-----', res);
}).catch((err) => {
// 讀取失敗的情況
console.log('用戶點擊-readText--err-----', err);
})
}
</script>頁面未獲取剪貼板訪問權限時:

有權限但頁面未獲取焦點時:

有權限且頁面獲取焦點時:

有權限且頁面獲取焦點,并觸發(fā)用戶行為:

文本內容base64查看:

所有內容base64查看:

③ write()
? 該方法用于寫入任意數據至系統(tǒng)剪貼板,參數為一個 ClipboardItem 對象數組(但每次只能包含一個 ClipboardItem 對象),里面包含了要寫入剪貼板的數據,返回值為一個 Promise 對象,經過異步操作之后,返回執(zhí)行結果。
? 目前主流瀏覽器都支持寫入的 MIME 數據類型有: text/plain 、 text/html 、 image/png 、 text/uri-list 。
④ writeText()
? 該方法用于寫入文本數據至系統(tǒng)剪貼板,參數為一個 String 字符串,表示要寫入剪貼板的文本數據,返回值為一個 Promise 對象,經過異步操作之后,返回執(zhí)行結果。
案例代碼:
<!-- 點擊選擇文件寫入到剪貼板 -->
<input type="file" onchange="clickWrite(event)">
<script>
// 在剛進入頁面時,先嘗試向剪貼板寫入內容
// 定義數據類型
const type = "text/plain";
// 創(chuàng)建一個blob對象
const blob = new Blob(['我是要通過write()寫入剪貼板的內容1111'], { type });
// 創(chuàng)建一個ClipboardItem對象數組
const data = [new ClipboardItem({ [type]: blob })];
console.log('data--', data);
// 將數據寫入剪貼板
window.navigator.clipboard.write(data).then((res) => {
console.log('write--res-----', res);
// 輸出剪貼板中的內容
window.navigator.clipboard.readText().then((res) => {
console.log('readText--res-----', res);
}).catch((err) => {
console.log('readText--err-----', err);
})
}).catch((err) => {
console.log('write--err-----', err);
})
// 因為讀寫都是異步操作 為了避免兩個寫操作互相干擾 所以等待1秒后 再嘗試向剪貼板寫入文本內容
setTimeout(() => {
window.navigator.clipboard.writeText('我是要通過writeText()寫入剪貼板的文本內容2222').then((res) => {
console.log('writeText--res-----', res);
// 輸出剪貼板中的內容
window.navigator.clipboard.readText().then((res) => {
console.log('readText--res-----', res);
}).catch((err) => {
console.log('readText--err-----', err);
})
}).catch((err) => {
console.log('writeText--err-----', err);
})
}, 1000)
// 用戶選擇圖片寫入剪貼板事件
function clickWrite (e) {
console.log('file--', e.target.files[0]);
// 定義數據類型
const type = "image/png";
// 創(chuàng)建一個ClipboardItem對象數組
const data = [new ClipboardItem({ [type]: e.target.files[0] })];
console.log('data--', data);
// 將數據寫入剪貼板
window.navigator.clipboard.write(data).then((res) => {
console.log('write--res-----', res);
// 輸出剪貼板中的內容
window.navigator.clipboard.read().then((res) => {
console.log('read--res-----', res);
}).catch((err) => {
console.log('read--err-----', err);
})
}).catch((err) => {
console.log('write--err-----', err);
})
}
</script>執(zhí)行結果:

3、ClipboardEvent
? 該接口繼承了 Event 接口,提供了有關系統(tǒng)剪貼板信息修改的事件,即 cut 、 copy 、 paste 事件,前端規(guī)范稱其為剪貼板事件(Clipboard Event API)。
? 我們可以通過 ClipboardEvent(type[, options]) 構造函數來創(chuàng)建 ClipboardEvent 對象,第一個參數 type ,是一個字符串,表示當前事件類型的名字,可以為: cut 、 copy 、 paste ,大小寫敏感;第二個參數 options 是可選的,內包含一個 clipboardData 屬性,該屬性的值是一個 DataTransfer 對象,包含了剪貼板事件所涉及的數據。
var clipboardEvent = new ClipboardEvent(type[, options]);
// 實例
var clipboardEvent = new ClipboardEvent('paste', {
clipboardData: new DataTransfer()
});? ClipboardEvent.clipboardData 屬性保存了一個 DataTransfer 對象,該對象有兩個用途:① 用于指定通過 cut 和 copy 事件寫入到剪貼板中的數據,通常使用 setData(format,data) 來指定數據。② 用于從 paste 事件中獲取想要從剪貼板中讀取的數據,通常使用 getData(fomat) 來獲取。 fomat 表示數據類型,例如: text/plain 、 text/uri-list 。
案例代碼:
var clipboardEvent = new ClipboardEvent('paste', {
clipboardData: new DataTransfer()
});
console.log('clipboardEvent--', clipboardEvent.clipboardData.getData('text/plain'));
clipboardEvent.clipboardData.setData('text/plain', 'Clipboard API來讀取剪貼板信息');
console.log('clipboardEvent--', clipboardEvent.clipboardData.getData('text/plain'));執(zhí)行結果:

4、ClipboardItem
? 該接口表示在使用read()和write()讀寫剪貼板數據時,單個數據的數據格式,該數據格式中將 MIME 類型作為 key ,將數據作為 value 。
① 創(chuàng)建ClipboardItem對象
? 可通過構造函數 ClipboardItem(data[, options]) 來創(chuàng)建該對象,第一個參數為想要存儲的數據,可以為 Blob 、 String 或 Promise (但個人開發(fā)發(fā)現 file 對象也可以);第二個對象參數表示數據的呈現形式,該對象只包含 presentationStyle 屬性,屬性值有三種: unspecified 、 inline 和 attachment . 默認值為 unspecified ,但是該屬性支持性特別差:Chrome、Edge、Firefox、Opera都不支持該屬性, Safari 支持該屬性,所以該屬性了解即可。
? 我們也可以通過 ClipboardItem.presentationStyle 來獲取當前對象的數據呈現形式。
new ClipboardItem(data[, options])
// 實例
const test = new ClipboardItem({ ["text/plain"]: new Blob(['我是小朱同學'], { "text/plain" }) }② 讀取ClipboardItem對象中的數據
? 首先我們可以通過 ClipboardItem.types 獲取當前 ClipboardItem 對象中所有MIME 類型組成的數組,然后再通過 getType(type) 方法來異步讀取對應的數據,返回一個Promise,讀取的數據為Blob類型:
ClipboardItem.types.forEach(type => {
ClipboardItem.getType(type).then(res => {
console.log('blob--', res);
})
})二、document.execCommand()
1、簡介
? 該方法用來操作當前聚焦的可編輯元素( input 、 textarea )中的內容,例如復制、剪貼、粘貼、刪除、文本加粗、插入圖片等等效果,有些富文本編輯器組件就是基于該API進行開發(fā)。而且該API的兼容性很好,可以兼容到 IE6 及以上。該API已經不推薦使用了,因為現在該API已經被 Clipboard 全面替代,雖然目前多數主流瀏覽器還支持使用,但隨時有可能被完全棄用。
瀏覽器兼容性:

2、基本語法
cosnt result = document.execCommand(aCommandName[,aShowDefaultUI,aValueArgument])
參數:
? ① aCommandName :一個命令字符串,表示要執(zhí)行操作的名稱,常用的有: copy 、 cut 、 paste 、 bold 等等,具體可查詢:execCommand。
? ② aShowDefaultUI :一個布爾值,表示是否展示用戶界面,一般為 false (Firefox不支持)。
? ③ aValueArgument :第一個參數中的某些命令需要的額外參數,默認為 null ,例如: insertImage 需要提供插入 image 的 url 。
返回值:
? ① 一個 Boolean :表示要執(zhí)行操作是否執(zhí)行成功( true ),若為 false ,則表示操作不被支持或操作失敗。
3、基本使用
function copyInputContent () {
// 設置想要復制的文本內容
const text = '讓我們一起快樂的敲代碼吧~';
// 創(chuàng)建一個input元素
let inputDom = document.createElement('textarea');
// 設置為只讀 防止移動端手機上彈出軟鍵盤
inputDom.setAttribute('readonly', 'readonly');
// 給input元素賦值
inputDom.value = text;
// 將創(chuàng)建的input添加到body
document.body.appendChild(inputDom);
// 選中input元素的內容
inputDom.select();
// 執(zhí)行瀏覽器復制命令
// 復制命令會將當前選中的內容復制到剪切板中(這里就是創(chuàng)建的input標簽中的內容)
// Input要在正常的編輯狀態(tài)下原生復制方法才會生效
const result = document.execCommand('copy')
// 復制操作后再將構造的標簽 移除
document.body.removeChild(inputDom);
}三、參考文檔
總結
到此這篇關于JavaScript實現點擊復制功能(JS訪問剪貼板相關)的文章就介紹到這了,更多相關JS點擊復制內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
通過Javascript創(chuàng)建一個選擇文件的對話框代碼
通過Javascript創(chuàng)建一個選擇文件的對話框代碼,需要的朋友可以參考下2012-06-06
JavaScrip如何安全使用Payment Request API詳解
這篇文章主要為大家介紹了JavaScrip如何安全使用Payment Request API詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10
微信小程序BindTap快速連續(xù)點擊目標頁面跳轉多次問題處理
這篇文章主要介紹了微信小程序BindTap快速連續(xù)點擊目標頁面跳轉多次問題處理,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-04-04

