JS實現複製大法

SaltAir發表於2018-12-21

之前是在一些類似於www.bootcss.com類似的網站見到過複製按鈕,點選之後一整行文字都可以複製,然後到指定的位置貼上就可以了,也知道這個是依託flash來實現的,剛好最近有一個需求是需要複製一段文字到剪貼簿,查了一下JS的實現方式,還是有些坑的。 能夠實現複製功能的方法是document.execCommand('copy'),可以參考MDN document.execCommand, 同時推薦看一下copy事件的文件。 我們都知道平時我們得的複製貼上都是選中一部分文字,然後按住ctrl + c來實現複製功能,那麼複製功能也需要先選中,再執行復制動作。如果事先在剪貼簿內已經有了內容,就不需要選中功能,直接執行貼上動作即可。 我本來的需求其實是進入一個頁面直接在使用者沒有任何操作的情況下直接執行,然後我做了一系列的實驗……首先放出我的demo~

<input id='ipt' value="我是要copy或者cut的內容"> 
<button id="btn">點選</button>
<script>
      var ipt = document.getElementById('ipt')
      var btn = document.getElementById('btn')
</script>
複製程式碼
//第一種模擬點選的方法是沒有什麼卵用的
    ipt.select()
    btn.onclick = function(){
        document.execCommand("Copy") 
        console.log(document.execCommand("Copy") )      //返回false
    }
    btn.click()     //這一步雖然可以選中文字 ,但是無法利用這個模擬點選去實現複製   
//很顯然,這樣不行 
複製程式碼
//我自己去進行點選,得到真實點選動作,可以完成複製或剪下
ipt.select()
   btn.onclick = function(){
       document.execCommand("Copy") 
       console.log(document.execCommand("Copy") )      //返回false
   }
//當我點選之後,控制檯返回了一個true,手動操作是可以實現的
複製程式碼
//試一下換成document.ready的時候複製,好像也不行耶……
ipt.select()
  window.onload = function(){
      document.execCommand("Copy") 
      console.log(document.execCommand("Copy") )      //返回false
  } 
//這樣並不能實現複製
複製程式碼
//最後,我很絕望,試試簡單粗暴、直接寫,看能不能執行
ipt.select()
document.execCommand("Copy") 
console.log(document.execCommand("Copy"))       //false
//事實證明,好像也不行
複製程式碼

各種實驗做下來,除非手動去點選按鈕獲取內容(不包含js模擬點選動作),否則無法實現複製功能(手機端使用touch相關的動作去實現也無效)。值得一提的是,我的html裡面是input元素,如果這個input是個readonly或disabled的情況,或者是input的type值為hidden,又或是input的css{display: none}我們都是無法實現select,無法選中文字的。但是我們可以把input的透明度設定為0,這樣做有個問題就是手機端容易暴露我們隱藏的內容,而且在使用者無意中點選到input的時候有一些瀏覽器會提示使用者謹慎輸入自己的資訊,以免造成不必要的損失之類的提示語。於是有了替代input的其他元素來進行選中,至於用什麼標籤,你開心就好啦:

<div id="aa">xxxxxxxxxxxxxx</div>
<button id="btn">dfhdddddd</button>
<script>
     var btn = document.getElementById('btn')
     function selectText(element) {
          var text = document.getElementById(element);
          if (document.body.createTextRange) {
              var range = document.body.createTextRange();
              range.moveToElementText(text);
              range.select();
           } else if (window.getSelection) {
              var selection = window.getSelection();
              var range = document.createRange();
              range.selectNodeContents(text);
              selection.removeAllRanges();
              selection.addRange(range);
              document.execCommand("Copy")     
            } else {
                alert("none");
            }
      }
      selectText("aa");
//這樣在剛開啟頁面的時候就可以看到已經選中的文字了
</script>
複製程式碼

在參考MDN的copy事件的時候,發現了這個描述:

使用者在瀏覽器介面進行復制行為的時候,會觸發copy事件(例如:使用CTRL/Cmd+C快捷鍵或者在選中選單欄點選"複製"命令)。copy事件會呼叫document.execCommand('copy')。當一個HTML文件切換到設計模式(designMode)時,文件物件暴露 execCommand方法,該方法允許執行命令來操縱可編輯區域的內容。大多數命令影響文件的選擇(粗體,斜體等),而其他命令插入新元素(新增連結)或影響整行(縮排)。當使用 contentEditable時,呼叫 execCommand() 將影響當前活動的可編輯元素。"

在執行copy動作的時候其實我們可以直接定義他需要複製的內容,這樣的話,即使使用者什麼也不選,那麼我麼也可以在他下次貼上的時候貼上的是我們規定好的內容:

document.addEventListener('copy', function(e){
    e.clipboardData.setData('text/plain', 'Hello, world!');
    e.preventDefault(); // We want our data, not data from any selection, to be written to the clipboard
});
//當我們在此頁面有複製動作的時候,在執行貼上動作,就會把hello,world
複製程式碼

然後我的需求到現在還沒有實現。。。我查了一些資料,stackoverflow上了解到:

1.png
2.png
3.png

大家的解釋都是關於安全方面的考量,不允許直接進行復制,必須是人作為主體來進行操作才能真正的執行復制這個動作;如果許可權過大可能會被利用來做一些有損使用者利益的事情。有關的回答大家可以參考這個網站: stackoverflow.com/questions/4…

相關文章