最近做的一个项目中,有一个点击按钮后,复制文本的需求,关于使用 JS复制文本的情况,很久以前曾经看到过,不过也仅是稍稍有些印象,对于到底如何复制,是否有什么兼容性要求等,都一概不知,但觉得应该没什么难度的。
但是当我自己真正做起来的时候,才发现这其中存在不少坑,各种浏览器实现复制的方法都不一样,而且无论怎么做兼容,似乎都不可能让所有的浏览器都能实现复制到粘贴板的功能。
几种主要方法总结如下。
execCommand
关于复制到粘贴板的功能,网上出现频率最多的方法就是 execCommand。
原理其实很简单明确,首先获取你想要复制的文本所在的元素,使用 js选择器即可,例如 document.getElementById('txt'),然后使用 select选择到文本,最后调用 execCommand方法进行复制。
function copy(){
let ele = document.getElementById('txt')
ele.select()
document.execCommand('Copy')
}
我用最新版 Chrome试验了一下,这里的 select()方法只对 input 或者 textarea 元素有效,只有txt是 这两个元素时,才有可能复制成功,其他元素全部失败。
这里需要说明的是,document.execCommand() 方法有很多参数,Copy只是其中一个:
// 选中网页中的全部内容
document.execCommand('selectAll')
// 打开 命令,相当于单击文件中的打开按钮
document.execCommand('open)
// 另存为 命令,将当前页面另存为
document.execCommand('saveAs)
// 打印 命令,需要存在打印机
document.execCommand('print)
// 剪贴选中的文字到剪贴板
document.execCommand('Cut','false',null)
// 删除选中的文字
document.execCommand(Delete','false',null)
....等等
以上就是document.execCommand()其中一部分使用方法,当然了,兼容性堪忧,几乎没什么浏览器实现,我用最新版的 Chrome操作以上方法,没一个有响应的。
除了配合 select之外,input元素还有一个 focus方法,同样可以达到此目的,例如,下面这段我直接从 MDN 抄来的代码。
<p>点击复制后在右边textarea CTRL+V看一下</p>
<input type="text" id="inputText" value="测试文本"/>
<input type="button" id="btn" value="复制"/>
<textarea rows="4"></textarea>
<script type="text/javascript">
var btn = document.getElementById('btn');
btn.addEventListener('click', function(){
var inputText = document.getElementById('inputText');
var currentFocus = document.activeElement;
inputText.focus();
inputText.setSelectionRange(0, inputText.value.length);
document.execCommand('copy', true);
currentFocus.focus();
});
</script>
我在谷歌浏览器上实验了一下,没什么卵用,因为人家已经注明了,除了 Firefox之外,其他浏览器全都没实现。
clipboardData
这个方法算是 IE的私有方法,有的文章上说 firefox也支持,可能之前比较古老的版本支持吧,我用最新版的火狐测试了一下,根本没用,其他浏览器应该也都没有(最起码我的chrome浏览器就不行。)
function copyToClipBoard(){
var clipBoardContent+=window.location.href;
window.clipboardData.setData("Text",clipBoardContent);
alert("复制成功");
}
上面代码我在 IE上试了一下,确实可行,不过其他浏览器就没反应了,因为根本没有 clipboardData这个方法。
IE的 clipboardData除了 setData这个方法之外,还有 getData(sDataFormat) 从剪贴板获取指定格式(text, url)的数据,以及清除剪贴板中指定格式(text, url)的数据 clearData(sDataFormat)
createTextRange
这个方法也只有在 IE下能用,我用 chrome 360se firefox分别测了一遍,全都报错。
<input onclick="goCopy(this)" value="这是要复制的内容">
function goCopy(obj){
obj.select()
textRange=obj.createTextRange()
textRange.execCommand("Copy")
alert("复制成功!")
}
这种方法似乎和第一种方法一样,但是还另外多了一行代码,就是这一句 js=obj.createTextRange() ,如果你要复制input或者 textarea元素中的所有内容,那么多出来的这一句是多此一举,但是如果你要只复制其中一部分文本,那么 这个 createTextRange()就能派上用场了,因为这个获得了 obj.createTextRange()的引用对象 textRange,还有其他的一些方法和属性,能够使得复制操作的颗粒度更小。
属性
| 属性名 | 描述 |
|---|---|
boundingHeight | 获取绑定 TextRange对象的矩形的高度 |
boundingLeft | 获取绑定TextRange 对象的矩形左边缘和包含TextRange对象的左侧之间的距离 |
offsetLeft | 获取对象相对于版面或由offsetParent属性指定的父坐标的计算左侧位置 |
offsetTop | 获取对象相对于版面或由offsetParent属性指定的父坐标的计算顶端位置 |
htmlText | 获取绑定TextRange对象的矩形的宽度 |
text | 设置或获取范围内包含的文本 |
方法
| 方法名 | 描述 |
|---|---|
| moveStart(‘character’, 2) | 更改范围的开始位置 |
| moveEnd | 更改范围的结束位置 |
| collapse | 将插入点移动到当前范围的开始或结尾 |
| move | 折叠给定文本范围并将空范围移动给定单元数 |
| execCommand | 在当前文档、当前选中区或给定范围上执行命令 |
| select | 将当前选择区置为当前对象 |
| findText | 在文本中搜索文本并将范围的开始和结束点设置为包围搜索字符串。 |
以上属性和方法在 IE中皆有效,其他浏览器都不行。
第三方库
关于复制粘贴功能,基本上就是以上三种了,其他的也都是从这三种方法中细化出来的方法,只是一个复制到粘贴板的功能就有那么多注意事项,还有那么多的兼容性代码要写,而且写了之后还不一定所有浏览器都能用,简直就是难为人嘛,不过按照我经验来看,这种情况越复杂繁琐,就越意味着妥妥的是要有第三方库的节奏啊,搜了一下,果然是有。
ZeroClipboard.js
ZeroClipboard.js是使用动态创建 flash的方式,并利用 flash将需要粘贴的文本或者其他对象粘贴到粘贴板的,也就是说需要浏览器支持 flash,flash的支持度确实很高,几乎所有浏览器都支持,但有的浏览器并不是默认支持 flash,必须要用户自己主动安装才行,比如 chrome,所有如果浏览器没有 flash,那么此库是用不了的。
除了一小部分不默认安装 flash的浏览器之外,此库在桌面上的兼容性很好,但是如今移动端基本上都是不支持 flash的,所以想要在移动端用,还是悠着点好。
clipboard.js
clipboard.js算是一个新锐了,在 github上迄今为止有 18500多颗星,号称是专为现代浏览器设计的复制粘贴方案,不使用 flash,不依赖其他库,gzip压缩之后只有 3kb的大小,兼容性为 IE9+。

此库实现复制粘贴功能使用的关键方法就是上面说到的 select() 和 execCommand两种结合,原理就是创建出一个隐藏的 input或者 textarea元素,结合两种方法进行复制粘贴。
这种方法在移动端也能用 ,但并不是所有的移动端浏览器都能用,据我测试情况来看,百度浏览器和chrome移动端都是可以用的,但是 QQ浏览器和 uc浏览器都不支持,如果不是必须要兼容所有浏览器,推荐使用此库,因为你能用更现代的方式来组织代码,例如在 vue等框架中使用此库。
以下为在 vue中使用 clipboard.js添加点击复制到粘贴板的功能示例。
<template>
<a href="javascript:;" @click="copyWx" :data-clipboard-text="wechat">复制微信</a>
</template>
<script>
// 引入 clipboard
import Clipboard from 'clipboard'
export default {
name: 'copyToClipboard',
props: ['wechat'],
methods: {
copyWx () {
let clipboard = new Clipboard('.wx')
clipboard.on('success', e => {
// 释放内存
clipboard.destroy()
})
clipboard.on('error', e => {
// 不支持复制
alert('浏览器不支持自动复制,请手动复制微信号')
// 释放内存
clipboard.destroy()
})
}
}
</script>
clipboard.js与ZeroClipboard.js二者相比各有优势,前者适合现代浏览器,使用方法也更加 modern 和 fashion,更贴近目前前端领域的发展趋势,这从它在github上的 star数量就可见一斑,后者则兼容性更强,虽然 flash目前已经宣布正式退休,但 想要让 flash彻底消失,还需要不短的时间,在这段时间内,ZeroClipboard.js依然可以有所作为。

本文探讨了使用JavaScript实现复制文本到剪贴板的各种方法及其兼容性问题。总结了execCommand、clipboardData及createTextRange等技术手段,并介绍了第三方库ZeroClipboard.js和clipboard.js的应用场景。
1051

被折叠的 条评论
为什么被折叠?



