最近項目中做一個很常見的復制粘貼的功能耽誤了比較長的時間特此記錄,在往常這個功能直接用 clipboard 做就行了,但是這次卻發現復制功能不好使了,雖然走了復制成功的回調,但是粘貼板并沒有復制的內容。代碼如下
<div v-for="item in arr">...<van-button v-if="status" class="copybtn" :data-clipboard-text="item.link" >復制</van-button>...
</div>
我們這個復制按鈕默認是隱藏的,用戶操作之后才會出來,經過一番查詢之后有文章指出,復制按鈕初始化的時候元素必須存在,并且不能 "display:none"的方式隱藏。
然后修改修改代碼邏輯, 按照文章指出的問題 v-if 換成v-show 也是不好使的,于是利用heigh:0來隱藏元素。測試環境測試ok。
本以為就此結束,后來上線發現,ios safari 還是不行,而且僅在線上環境復現。我一直覺得clipboardjs 這么常用的庫應該不會有問題,應該是用法的問題,但因為本地的代理工具除了問題,無法抓包ios調試。給排查問題造成了較大的困難。經過幾次調整嘗試后仍然無法解決而且耽誤較多的時間。于是轉換思路,利用原生復制功能,雙管齊下,但發現原生的navigator.clipboard 雖然是標準仍然有兼容性問題,安卓真機復制失敗。于是有加上兼容性更好,但標準廢棄的document.execCommand ,最終解決了問題針機測試ok。代碼實現如下
<van-button class="copybtn" :class="{hidden:status==0}" :data-clipboard-text="item.link" @click="copyToClipboard(item.link)">復制</van-button>
export default {mounted(){this.$nextTick(()=>{var clipboard = new Clipboard('.copybtn');clipboard.on('success', (e) => {this.$toast.success('復制成功');e.clearSelection();});clipboard.on('error', e => {this.$toast.fail('復制失敗');});}) },methods:{copyToClipboard(text) {navigator.clipboard.writeText(text).then(() => {this.$toast.success('復制成功');console.log('復制成功[navigator.clipboard]:', text);}).catch(err => {console.error('復制失敗:', err);this.copyForExecCommand(text) //復制失敗用改用document.execCommand});},copyForExecCommand(text) {// 創建臨時 textarea 元素const textarea = document.createElement('textarea');textarea.value = text;textarea.setAttribute('readonly', ''); // 設置為只讀,防止 iOS 設備出現問題textarea.style.position = 'absolute';textarea.style.left = '-9999px'; // 將其放在屏幕外面document.body.appendChild(textarea);// 選擇并復制內容到剪貼板textarea.select();document.execCommand('copy');// 移除臨時元素document.body.removeChild(textarea);this.$toast.success('復制成功');console.log('復制成功[document.execCommand]:', text);},}
}