在前端平常開發中,對剪貼板相關的操做相對較少。但針對某些特定的應用場景,又是必不可少會用到的。好比:富文本編輯器開發、ctrl + v 上傳圖片、支付寶紅包口令自動複製(典型被玩壞兒了的用途)javascript
操做剪貼板,最基礎的方式爲監聽剪貼板事件。出於兼容性考慮,通常都只在剪貼板事件處理函數中訪問 clipboardData ,非 IE 瀏覽器讀數據只能在 onpaste 事件時可用。要使用剪貼板事件讀寫數據,就必須得用戶主動使用快捷鍵或者右鍵菜單。因此監聽板事件的主要應用場景是用戶觸發後對數據進行攔截處理。html
document.execCommand() 方法用於操縱可編輯區域的內容,例如最經常使用的 'copy' 命令可將選擇區域的內容複製到剪貼板中,配合 window.getSelection() 方法就能夠實現自動選擇內容區域並寫入內容到剪貼板。clipboard.js 庫及紅包口令自動複製主要就經過此方法實現的。前端
此方法也有一些問題:java
看過上面的介紹,你會發現,操做剪貼板到處受限,並且迂迴曲折,更困難的是有些功能是沒法實現的。但不能否認,形成這一困惑很大一部分緣由是安全考慮。node
試想一下,當你瀏覽網頁,點了下頁面或者按鈕,就複製了支付寶紅包口令,會怎樣?呃,還能接受?那麼 'rm -rf /' 呢?(我用 Windows,我怕啥)ios
而作爲 Clipboard API 新增內容的 Asynchronous Clipboard API 及 Clipboard Permissions API 就是爲了解決上述問題而來的,專治各類迂迴曲折及安全風險。截至目前(2018.03),Chrome 66 實現了部分功能,預測將來會有變化,本文不作詳細介紹。暫概括特色以下:git
對於粘貼,目前普遍支持的僅有快捷鍵及右鍵菜單觸發,而 IE 支持的編程方式使用場景很少,這裏不作介紹。github
對純文本的攔截編程
El.addEventListener('paste', event => {
event.preventDefault();
let clipboardData = event.clipboardData || window.clipboardData, // IE 兼容
plainText = clipboardData.getData('text'); // 無格式文本
// ... 對 plainText 進行一系列處理操做
document.execCommand('insertText', false, plainText); // 插入無格式文本
document.execCommand('paste', false, plainText); // IE 兼容
})
複製代碼
如需對有格式文本進一步處理,可用如下方法轉換爲 DOM 結構,再進行操做。(IE 瀏覽器沒法得到 'text/html' 因此沒法實現下面的功能)api
/* 仍在上述事件處理函數中,下面均省略 */
let plainHTML = clipboardData.getData('text/html'), // 有格式文本
domContainer = document.createElement('div');
domContainer.innerHTML = plainHTML;
// ... 對 domContainer 進行一系列處理操做
El.innerHTML = domContainer.innerHTML; // 使用 innerHTML 方式總體插入
El.appendChild(nodeOfDomContainer); // 只插入其中某個節點
複製代碼
如 DOM 結構中含有圖片標籤,可考慮上傳圖片至服務器中,而後將其 src 替換爲服務器返回的地址。
如複製的是單個圖片(例如 word 中複製過來的),可使用下述方法獲得圖片的 DataURL,再上傳。(IE 瀏覽器粘貼圖片會自動生成帶 DataURL 的圖片標籤,因此不須要下述方法)
let items = clipboardData.items;
for (let i = 0; i < items.length; i++) {
let item = items[i];
if (/image/.test(item.type)) {
let file = item.getAsFile(), // 獲得文件對象
reader = new FileReader();
reader.onload = function() {
upload(reader.result) // 上傳圖片,僞代碼
}
reader.readAsDataURL(file); // 讀取爲 DataURL / Base64
}
}
複製代碼
常見應用場景是攔截複製操做,對複製內容加工後再寫入剪貼板,例如在知乎複製大段文本後加入版權信息。
El.addEventListener('copy', event => {
event.preventDefault();
let clipboardData = event.clipboardData || window.clipboardData,
text = window.getSelection().toString();
// ... 對 text 進行一系列處理操做
clipboardData.setData('text/plain', text); // 將處理好的 text 寫入剪貼板
clipboardData.setData('text', text); // IE 兼容
})
複製代碼
雖是編程式複製,但沒法作到徹底自動複製,須要用戶先觸發 點擊 事件。clipboard.js 庫及紅包口令自動複製(在 document 上監聽 click 事件)主要就經過此方法實現的。
固定內容
Button.addEventListener('click', event => {
let sometext = '紅包碼 xxxxxx',
hiddenInput = document.createElement('input');
hiddenInput.value = sometext;
hiddenInput.setAttribute('readonly', '');
hiddenInput.style.position = 'absolute';
hiddenInput.style.left = '-9999px';
document.body.appendChild(hiddenInput);
hiddenInput.select();
hiddenInput.setSelectionRange(0, hiddenInput.value.length); // ios
document.execCommand('copy');
document.body.removeChild(hiddenInput);
})
複製代碼
複製某個元素內的文本
Button.addEventListener('click', event => {
let someElement = document.getElementById('someelement'),
selection = window.getSelection(),
range = document.createRange();
range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
})
複製代碼
能夠發現,目前對剪貼板的操做真是千奇百怪,但願新的 API 快快成爲現實吧(
作夢)!
[1] Clipboard API and events | w3c
[3] 利用 javascript 實現富文本編輯器 | 掘金
[4] 富文本編輯器初探 | 掘金