最近项目中做一个很常见的复制粘贴的功能耽误了比较长的时间特此记录,在往常这个功能直接用 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);
},
}
}