H5移動端實現一鍵復制或長摁復制


今天接到了一個新的需求,要求我們對表單中的某一個字段進行復制,這個表單是不可選的,拿到需求的時候有點懵,不清楚下手點在哪,后來網上找了找,終於有了點眉目,感覺網上有些是實現不了的,特地在這里記錄下進行總結

實現復制功能,因為需求沒有明確提出是要一鍵復制,還是長摁復制,所以把兩種都講了吧

正常來說一鍵復制只需要在onclick事件即可,但是因為我的表單是disabled狀態的,他沒辦法執行onclick

所以走了捷徑,直接用 ontouchstart 如果要長摁,就加入一個定時器就好了

直接上代碼吧

  const copy = document.getElementById('text-surveyPreRequirementCode')

  if (copy) {
    copy.ontouchstart = function () {
      CopyId(copy)//此處可以加入定時器來設置他是點擊事件還是長摁事件,如你們的表單不是disabled,就直接用onclick
    }
  }

  const CopyId = async (copyDOM: any) => {
    console.log(copyDOM.textContent);
    try {
      const clipboardObj = navigator.clipboard;
      await clipboardObj.writeText(copyDOM.textContent)
      Toast.info('復制成功')
    } catch (error) {
      Toast.info(`錯誤,${error}`)
    }
  }

看了網上的博客,大家的做法大多是用

document.execCommand("copy") 

貼一下別人的代碼

CopyOrderSerialId() {
              var system = navigator.userAgent;//獲取系統信息
              //蘋果
              if (system.match(/(iPhone|iPod|iPad);?/i)) {
               window.getSelection().removeAllRanges();   //將頁面所有的文本區域都從選區中移除
              var copyDOM = document.getElementById("orderId-copy"); //要復制文字的節點
              var range = document.createRange();
              // 選中需要復制的節點
              range.selectNode(copyDOM);
              // 執行選中元素
              window.getSelection().addRange(range);
              // 執行 copy 操作
              var successful = document.execCommand('copy');
              try {
              var msg = successful ? '成功' : '失敗';
                this.$toast("復制"+msg );
              } catch (err) {
                // this.$toast("復制失敗,請從事");
              }
              // 移除選中的元素
              window.getSelection().removeAllRanges();
              }
              // 安卓
              if (system.indexOf('Android') > -1) {
                var orderUrl = this.orderData.OrderSerialId;// 獲取訂單號
                var newInput = document.createElement("input");// 這里的邏輯就是新建立一個input標簽,
                newInput.value = orderUrl +'';// 把訂單號設置為input的value值 
                document.body.appendChild(newInput);// 把input添加到body中
                newInput.select(); // select 選中input里面的所有文本內容
                document.execCommand("Copy"); // 執行瀏覽器復制命令
                document.body.removeChild(newInput);   // 最近需要銷毀
                this.$toast("復制成功");//調用引入的輕提示插件告訴用戶復制成功
              }
          },
————————————————
版權聲明:本文為CSDN博主「無所事事的小老弟」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/fengkui347235/article/details/103906709

在用 document.execCommand("Copy") 會有一個很大的坑:他沒辦法異步!!!

無法異步,意味着你ajax請求的數據是無法復制的,我們都知道ajax是異步請求的,而document.execCommand("Copy")沒辦法異步執行,因此無法及時的復制文本

document.execCommand()這個api只能在真正的用戶操作之后才能被觸發,是為了安全考慮。原理大致是這樣的,當用戶操作之后,chrome會將當前作用域下的userAction變量置為True(編的變量名),然后執行execCommand時就會去讀取這個變量,當為True的時候才可以執行。

因為ajax基本都是異步請求,而異步請求不同於同步請求的地方就在於重新創建了一個作用域去執行回調函數。
所以在重新創建一個作用域之后,之前作用域內的userAction就失效了,當前作用域下的userAction為false,所以復制不成功。

解決辦法

  1. 用真正的用戶操作去執行execCommand。(可能需要修改交互流程)
  2. 將異步請求改成同步請求。這樣做就不會創建新的作用域,execCommand命令依舊在userAction為true的上下文下執行。(當然這種做法也不是很推薦,但為了滿足需求只能這樣做,只要把xhr.open里的最后一個參數改為false即可滿足同步請求)

不過說真的,無法理解,只好另辟蹊徑

這是發現了一個新的api(在阮一峰那找到的,感興趣的建議去看看,鏈接:http://www.ruanyifeng.com/blog/2021/01/clipboard-api.html)

Clipboard

Clipboard API 是下一代的剪貼板操作方法,比傳統的document.execCommand()方法更強大、更合理。

它的所有操作都是異步的,返回 Promise 對象,不會造成頁面卡頓。而且,它可以將任意內容(比如圖片)放入剪貼板。

navigator.clipboard屬性返回 Clipboard 對象,所有操作都通過這個對象進行。

在這里我就只介紹我用的方法吧

Clipboard.writeText()

Clipboard.writeText()方法用於將文本內容寫入剪貼板。這樣子你就可以粘貼了

使用這個辦法,異步的問題就解決了。

但是有一個問題就是他的兼容性有待商榷

歡迎大家多多探討


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM