实现点击按钮自动复制剪贴板功能,并解决ios不兼容问题

4,054 阅读3分钟

前言

昨天接到一个需求,实现一个推广页,其中有一个功能是点击按钮自动复制文字,看起来so easy。万万没想到,就这个自动复制功能,花费了我几个小时,接下来就是我的填坑过程,过程艰辛,结果简单。

实现原理

参考平时复制文本的思路,选中文本,ctrl+c或右键菜单复制。那么只要我们能利用js选中文本,并且能找到浏览器复制选中文字到剪贴板的调用方法,我们就能实现这个需求。

实现过程与方法

1.自己手撸js实现

html代码:

<div id="copy_wx">
    <span>点击复制</span>
    <iput id="id_text" type="text" value="复制的内容" readonly style="position: absolute;left: -1000px;"/>
</div>

js代码:

$('#copy_wx').click(function(){
    $('#id_text').select();//选中文字
    document.execCommand('copy');//拷贝当前选中内容到剪贴板
})

发现苹果手机复制不了,用can I use查,才知道,是onselect的兼容性问题,安卓手机没有问题,但是苹果手机不兼容。

没关系,此路不通,咱可另寻出路,几番百度,终于找到选中文字的另一个方法——HTMLInputElement.setSelectionRange ,兼容性良好,就是它没错了。HTMLInputElement.setSelectionRange 方法可以从一个被 focused 的 <input> 元素中选中特定范围的内容,这个方法需要结合focus事件一起用。

$('#copy_wx').click(function(){
    var element = $('#id_text')
    element.focus();
    element.setSelectionRange(0, element.val().length);
    document.execCommand('copy');//拷贝当前选中内容到剪贴板
    element.blur();
})

除了自己手撸代码,网上也提供了另外一种可以更优雅的实现复制粘贴功能。下面我们简单介绍一下clipboard插件,以及遇到的一些问题。

2.clipboard插件实现

这是一个不需要依赖flash或者其他复杂框架的轻量插件,详细的可以参考clipboard文档

html代码:
<div id="btn1" data-clipboard-text="555">
    <span>点击复制4</span>
</div>
<script src="https://cdn.bootcss.com/clipboard.js/2.0.6/clipboard.min.js"></script>
js代码:
var clipboard = new Clipboard('#btn1')
clipboard.on('success', e => {
    alert('复制成功');
});
clipboard.on('fail', e => {
    alert('复制失败');
})

非常简单好用,但开始测试时,发现有些iphone手机(如:iphone6)会复制不成功,后面改用以下方法:

<div
    id="btn1" data-clipboard-action="copy" data-clipboard-target="#id_text"
>
    <span>点击复制</span>
    <input id="id_text" type="text" value="666"
    />
</div>

复制的文字是在视图窗口可见的状态下,是可以复制成功的,但是我们的需求是希望复制的文字不需要可见的。于是又出现了新的问题,如果将input用绝对定位position: absolute;left: -9999px移出视图窗口,或者用层级position: absolute;z-index: -1;置于按钮之下,以达到文字消失的视觉效果,文字看不见了,但在一些iphone手机(如:iphone6)复制粘贴功能也没了。(说明一下:当时这个需求是在基于JQuery开发的项目中的,但后面我自己在vue脚手架的demo实验,这个问题不存在。这个问题目前我不知道是啥问题,读者如果知道的话,欢迎留言。)

莫非就没有解决方法了?不,我们还有一个比较笨的方法,我们可以将文字的颜色设置成与按钮的背景色一样,这样同样可以达到视觉不可见的效果。当然,有其他的解决方案的话,也欢迎留言。

注意
在vue中使用中,如果是用的data-clipboard-text,在路由组件跳转中,并不能销毁掉clipboard绑定的事件
造成结果:重复绑定事件
解决方法:可以在vue的beforeDestroy中调用clipboard的destroy()进行销毁

总结

这个问题不大,但有时找不到方法的话也挺耗时的,希望这篇文章可以给某些踩坑中的同学一点帮助。