在实现需求时会遇到了点击某一文本,将其内容复制到粘贴板的功能。虽然现在已经有了很多方便快捷的组件(例如第三方库:clipboard.js),但是考虑到兼容性等问题,我还是选择了通过js原生方法
document.execCommand()
来实现这个功能。
使用框架:vue。
第一次尝试-从输入框复制
使用document.execCommand()
之前,需要先了解一下这个API是什么:document.execCommand()
简单介绍一下:
- 语法
bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)
- 返回值
一个Boolean
,如果是 false 则表示操作不被支持或未被启用。 - 参数
aCommandName
一个DOMString
,命令的名称。可用命令列表请参阅 命令 。
aShowDefaultUI
一个Boolean
, 是否展示用户界面,一般为 false。Mozilla 没有实现。
aValueArgument
一些命令(例如insertImage
)需要额外的参数(insertImage
需要提供插入image
的url
),默认为null
。 - 常用命令
document.execCommand()
提供了很多常用的命令,比如backColor
(修改文档的背景颜色),bold
(开启或关闭选中文字或插入点的粗体字效果),copy
(拷贝当前选中内容到剪贴板),cut
(剪贴当前选中的文字并复制到剪贴板)等等。这次用到的就是copy
了。
最后,最重要的一点:document.execCommand()
允许运行命令来操作可编辑区域的内容。
因此,我选择了input
元素作为我的内容承载元素。
<input id="demoInput" value="hello world" />
<button id="btn" @click='copy'>点我复制</button>
copy(){
const input = document.querySelector('#demoInput');
input.focus(); // 获取input焦点
input.setSelectionRange(0, input.value.length); //获取input内容,想截取多少内容可以在这里计算
const res = document.execCommand('copy', true)
if (res) {
console.log('复制成功');
}else{
console.log('复制失败');
}
input.blur();
}
// 取消选中样式
#demoInput::selection{
background-color:unset;
}
这样就基本实现了这个功能啦。
第二次优化-从其他地方复制
功能是实现了,但是实际上却发现,使用了input
元素的样式与其他地方差异很大,想当然这样是过不了UI审核的,既然这样,那我们可以选择创建一个不可见的input
元素来实现复制功能,展示部分还是与其他地方一致。
<div id="demoInput" value="hello world" />
<button id="btn" @click='copy'>点我复制</button>
copy(){
const input = document.createElement('input');
input.setAttribute('value', 'hello,world');
document.body.appendChild(input);
input.focus();
input.setSelectionRange(0, input.value.length);
let res = document.execCommand('copy', true);
if (res) {
console.log('复制成功');
} else {
console.log('复制失败,请重试');
}
input.blur();
document.body.removeChild(input);
}
这样就既实现了功能又保证了样式的统一。
最终优化-小bug优化
经过上次的优化后,还是有一些问题存在,比如ios上执行这个复制方法时屏幕下方会出现白屏抖动(拉起键盘又瞬间收起),再比如由于input元素是插到body里的最后一个子元素下,所以在屏幕有滚动并且聚集input元素时,会自动定位到该元素,我尝试过直接插入到需要复制的元素下,但是还是会有滑动。
最终方案:
<div id="demoInput" value="hello world" />
<button id="btn" @click='copy'>点我复制</button>
copy(){
const input = document.createElement('input');
input.setAttribute('readonly', 'readonly');// 设置只读,不拉起键盘
input.setAttribute('value', 'hello,world');
document.body.appendChild(input);
input.select(); // 不用focus()聚集,直接选择input所有内容
input.setSelectionRange(0, input.value.length);
// 除ios环境外,其他环境使用select()就能够复制input的内容
let res = document.execCommand('copy', true)
if (res) {
console.log('复制成功')
} else {
console.log('复制失败,请重试')
}
document.body.removeChild(input)
}
这里就是我最终使用的方案了,目前使用效果良好。感谢大佬的分享,在这只能感叹一句:大佬肩膀上的风景真好啊。。。。。
大佬的文章: JavaScript复制内容到剪贴板