向下兼容
下面将分别介绍使用document.execCommand (‘copy’)实现文本和图片复制的具体方法。
由于目前仍存在很多不支持Clipboard API的环境,因此向下兼容是不可或缺的。
复制文本
上文有提到,古老的复制方法要基于页面选中的内容,而一键复制,即用户无感知复制过程,仅需要一个已成功拷贝到剪贴板的结果。
因此就不能手动选中了,可以用Web API提供的select()方法(文本专用)选中复制目标内容,再调用复制方法进行拷贝操作。
已知select()方法仅在input类型的元素中提供,也就是如文档所说的或type值为text的<input>。</span>
思路与代码:
1. 创建临时textarea元素,选中目标内容
/* 定义要复制的目标字符串 */
const text = '目标内容';
/* 选中内容 */
const txa = document.createElement('textarea');
txa.innerHTML = text;
document.body.appendChild(txa);
txa.select(); // 调用select()选中文本内容
2. 复制,后移除临时textarea元素
/* 拷贝操作 */
document.execCommand('copy'); // 到此为止 复制操作完成
/* 移除临时textarea */
document.body.removeChild(txa);
复制图片
由于选中页面文本使用select()方法仅支持input类型元素,因此无法实现选中图片。
这就需要请出Web API提供的getSelection()和createRange()方法,可通过设置当前页面的选中范围并获取这个范围,来达到获取选中图片的效果,其本质是选中一个DOM中的图片结点。
思路与代码:
1. 新建Selection对象创建选区,获取图片结点
HTML部分(适用于要复制的图片已经存在于DOM):
<img id="img1" src="https://cos.ap-shanghai.myqcloud.com/96fb-shanghai-180-sharedv4-01-1303031839/15df-1400798275/5eb2-46648b08a1dc9f874767187454986dc0/7e25d051dd2cfebfb832023708295f96-292349.png?imageMogr2/" />
注意:直接使用已经存在于DOM的图片结点,会产生一个小问题,就是如果对该图片有特殊的样式设置,比如设置了于原图不同的宽高或者设置了圆角,那么复制出来的图片也会保留这些样式。
因此如果确定使用这种方式,那可以在图片外边包一层来设置样式,别把个性化样式写在img上就可以了。
如果需求中要复制的图片当前不存在于DOM中,则同样可以创建一个临时的imgNode,完事再给它remove掉。
const imgNode = document.createElement('img');
imgNode.src = 'https://cos.ap-shanghai.myqcloud.com/96fb-shanghai-180-sharedv4-01-1303031839/15df-1400798275/5eb2-46648b08a1dc9f874767187454986dc0/7e25d051dd2cfebfb832023708295f96-292349.png?imageMogr2/';
document.body.appendChild(imgNode);
JS部分:
const sel = window.getSelection(); // 新建选区
const imgNode = document.getElementById('img1'); // 获取图片结点
2. 新建Range对象,将Range设置为包含整个图片结点及其内容,并向选区中添加Range对象
sel.removeAllRanges(); // 清除当前页面所有已选中范围:会导致手动选中的内容也被取消
const range = document.createRange(); // 新建范围
range.selectNode(imgNode); // 将范围包含整个图片结点内容
sel.addRange(range); // 向选中中添加该范围
3. 复制,后移除选区中的Range
document.execCommand('copy'); // 复制
sel.removeAllRanges(); // 清除已选中范围 若无这一步 复制后图片将仍处于选中状态
题外话:用向下兼容的方式复制出来的图片在粘贴时可能不如推荐方法复制的图片适应性好,因为它本质复制的是’text/html’格式的内容,而非’image/*'格式,因此想要完美粘贴图片,对于你目标粘贴的位置 对这种格式的数据的解析也有一定要求。
当然我有实现一个支持粘贴’text/html’格式的可编辑框,不过它的实现方式不在本文讨论范围内。
关于该方法一个需要注意的点:在执行document.execCommand(‘copy’)前,需要在当前页面有过至少一次点击操作,也就是如果页面加载完成后立即自动调用,复制操作会无效。无相关文档考证,猜测这是浏览器一个类似于禁止用户无操作情况下就自动播放音频的保护机制。
到此所有方法及其细节介绍完毕。
小结
以上就是本次要介绍的关于“使用js实现一键复制”的全部内容,感谢您看到这里。
其实目前有了chatGPT,好像本文这类总结显得不那么重要了,因为只要调整好你的问题,chatGPT可能就会给一个参考性非常强的答案。我也拿着本文想要讨论的问题问了chatGPT,果然它首先就推荐了本文用到的基于Clipboard API的方法,再深入问一下兼容方案,它也开始提到 document.execCommand(‘copy’)方法,不过按照它的步骤走一遍,好像并不是完全无语法错误的答案,更不符合我本次的要求。
作者:牛思佳
来源:微信公众号:好未来技术
出处:https://mp.weixin.qq.com/s/gTCiWGNwfIrgykpSJW69hA