前言
有時候我們經常會碰到這些場景:玩掘金、知乎的時候複製一段文字,總是會在內容後面加上一些版權資訊,以及像小說網站等都有禁止選中,禁止複製這種功能,還有點選自動複製賬號的功能。
我也經常遇到這些場景,有時候會去想這後面到底是怎麼做,週末趁著有空去研究了一下,然後發現這些都跟操作剪貼簿有關係,並且都不難,瞭解一下基本都知道怎麼做了,整理分享一波給大家。
個人部落格瞭解一下:obkoro1.com
目錄:
- API介紹
- 實現類知乎/掘金複製大段文字新增版權資訊
- 實現類起點網的防複製功能
- 破解防複製
- 點選複製功能
API介紹:
複製、剪下、貼上事件:
copy
發生複製操作時觸發;cut
發生剪下操作時觸發;paste
發生貼上操作時觸發;- 每個事件都有一個before事件對應:
beforecopy
、beforecut
、beforepaste
;
這幾個before一般不怎麼用,所以我們把注意力放在另外三個事件就可以了。
觸發條件:
-
滑鼠右鍵選單的
複製
、貼上
、剪下
; -
使用了相應的鍵盤組合鍵,比如:
command+c
、command+v
;就算你是隨便按的,也會觸發事件。高程中介紹在
Chorme
、Firefox
和Safari
中,這幾個before事件只會在真實會發生剪貼簿事件的情況下觸發,IE上則可以觸發before。我實際測試的時候最新版chorme
也會亂按也會觸發,所以限制應該是在早一點的版本上。so 想說的是:before這幾個事件最好不要用,有關於剪下板的處理最好放在
copy
、cut
、paste
上面。
使用姿勢:
以copy為例:
document.body.oncopy = e => {
// 監聽全域性複製 做點什麼
}
// 還有這種寫法:
document.addEventListener("copy", e => {
// 監聽全域性複製 做點什麼
});
複製程式碼
上面是在document.body
上全域性監聽的,然而很多人不知道的是,我們還可以為某些dom單獨新增剪下板事件:
// html結構
<div id="test1"></div>
<div id="test2"></div>
// 寫法一樣:
let test1 = document.querySelector('#test1');
test1.oncopy = e => {
// 監聽test1發生的複製事件 做點什麼
// test1發生的複製事件會觸發回撥,其他地方不會觸發回撥
}
複製程式碼
其他事件也是一樣的,這裡就不贅述了。
clipboardData物件:用於訪問以及修改剪貼簿中的資料
相容:
不同瀏覽器,所屬的物件不同:在IE中這個物件是window
物件的屬性,在Chrome
、Safari
和Firefox
中,這個物件是相應的event
物件的屬性。所以我們在使用的時候,需要做一下如下相容:
document.body.oncopy = e => {
let clipboardData = (e.clipboardData || window.clipboardData);
// 獲取clipboardData物件 + do something
}
複製程式碼
物件方法:
物件有三個方法: getData()
、setData()
、clearData()
-
getData()
訪問剪下板中的資料引數:
getData()
接受一個'text'
引數,即要取得的資料的格式。在複製、剪下、貼上觸發的事件的資料:
實際上在chorme上測試只有
paste
貼上的時候才能用getData()
訪問到資料,用法如下:要貼上的資料:
document.body.onpaste = e => { let clipboardData = (e.clipboardData || window.clipboardData); // 相容處理 console.log('要貼上的資料', clipboardData.getData('text')); } 複製程式碼
被複制/剪下的資料:
在複製和剪下中的資料,需要通過
window.getSelection(0).toString()
來訪問:document.body.oncopy = e => { console.log('被複制的資料:', window.getSelection(0).toString()); } 複製程式碼
-
setData():
修改剪下板中的資料引數:第一個引數也是
'text'
,第二個引數是要放在剪下板中的文字。剩下的留在下面仿知乎/掘金複製大段文字新增版權資訊那裡再說。
-
clearData()
:這個方法就不太知道了,試了好久不知道怎麼用(如果有大佬知道,可以在評論區指點一下)。
如果只是為了禁止複製,或者禁止貼上,在下面還有另外的方法可以做到,並且可以細粒化操作。
應用:
如果學習不是為了裝X,那麼一切將毫無意義,來看這個東西可以在哪些場景使用:
實現類知乎/掘金複製大段文字新增版權資訊:
實現很簡單:取消預設複製之後,主要是在被複制的內容後面新增資訊,然後根據clipboardData的setData()方法將資訊寫入剪貼簿。
可以直接複製這段程式碼到本地去試試。
// 掘金這裡不是全域性監聽,應該只是監聽文章的dom範圍內。
document.body.oncopy = event => {
event.preventDefault(); // 取消預設的複製事件
let textFont, copyFont = window.getSelection(0).toString(); // 被複制的文字 等下插入
// 防知乎掘金 複製一兩個字則不新增版權資訊 超過一定長度的文字 就新增版權資訊
if (copyFont.length > 10) {
textFont = copyFont + '\n'
+ '作者:OBKoro1\n'
+ '連結:https://juejin.im/user/58714f0eb123db4a2eb95372/posts\n'
+ '來源:掘金\n'
+ '著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。';
} else {
textFont = copyFont; // 沒超過十個字 則採用被複制的內容。
}
if (event.clipboardData) {
return event.clipboardData.setData('text', textFont); // 將資訊寫入貼上板
} else {
// 相容IE
return window.clipboardData.setData("text", textFont);
}
}
複製程式碼
然後command+c、command+v,輸出:
你複製的內容
作者:OBKoro1
連結:https://juejin.im/user/58714f0eb123db4a2eb95372/posts
來源:掘金
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
複製程式碼
實現類起點網的防複製功能:
- 禁止複製+剪下
- 禁止右鍵,右鍵某些選項:全選,複製,貼上等。
- 禁用文字選擇,能選擇卻不能複製,體驗很差。
- user-select 用css禁止選擇文字。
可以把程式碼拷到本地玩一玩:
// 禁止右鍵選單
document.body.oncontextmenu = e => {
console.log(e, '右鍵');
return false;
// e.preventDefault();
};
// 禁止文字選擇。
document.body.onselectstart = e => {
console.log(e, '文字選擇');
return false;
// e.preventDefault();
};
// 禁止複製
document.body.oncopy = e => {
console.log(e, 'copy');
return false;
// e.preventDefault();
}
// 禁止剪下
document.body.oncut = e => {
console.log(e, 'cut');
return false;
// e.preventDefault();
};
// 禁止貼上
document.body.onpaste = e => {
console.log(e, 'paste');
return false;
// e.preventDefault();
};
// css 禁止文字選擇 這樣不會觸發js
body {
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
複製程式碼
PS:
- 使用
e.preventDefault()
也可以禁用,但建議使用return false
這樣就不用去訪問e
和e
的方法了。 - 示例中
document.body
全域性都禁用了,也可以對dom(某些區域)進行禁用。
破解防複製:
上面的防複製方法通過js
+css
實現的,所以思路就是:禁用js
+取消user-select
樣式。
Chrome
瀏覽器的話:開啟瀏覽器控制檯,按F1
進入Setting
,勾選Disable JavaScript
(禁止js)。
此時如果還不能複製的話,就要去找user-select
樣式,取消這個樣式就可以了。
所以那些盜版小說手打的,我真的不太能理解,Excuse me???
點選複製功能:
不能使用clipboardData:
在IE中可以用window.clipboardData.setData('text','內容')
實現。
上文提到過,在IE中clipboardData
是window
的屬性。
而其他瀏覽器則是相應的event
物件的屬性,這實際上是一種安全措施,防止未經授權的訪問,為了相容其他瀏覽器,所以我們不能通過clipboardData
來實現這種操作。
具體做法:
-
建立一個隱藏的
input
框 -
點選的時候,將要複製的內容放進
input
框中 -
選擇文字內容
input.select()
這裡只能用
input
或者textarea
才能選擇文字。 -
document.execCommand("copy"),執行瀏覽器的複製命令。
function copyText() { var text = document.getElementById("text").innerText; // 獲取要複製的內容也可以傳進來 var input = document.getElementById("input"); // 獲取隱藏input的dom input.value = text; // 修改文字框的內容 input.select(); // 選中文字 document.execCommand("copy"); // 執行瀏覽器複製命令 alert("複製成功"); } 複製程式碼
點選複製內容的demo在這裡,可以點進去看看。
結語
工作之餘瞭解一下這些東西還是很有趣的,也可以擴寬你的知識面。
事實上只要監聽了這些事件,我們就可以對要剪下的內容進行各種各樣的操作,比如:複製的時候更換文字,貼上的時候查詢有沒有圖片(上傳圖片),或者文字的長度進行剪下等等,唯一限制你的
希望看完的朋友可以點個喜歡/關注,您的支援是對我最大的鼓勵。
部落格、前端積累文件、公眾號、GitHub、wx:OBkoro1、郵箱:obkoro1@foxmail.com
以上2018.8.8
參考資料:
js高程 14.2.2操作剪貼簿