前言
最近做了一个关于这方面的需求,自己也是第一次做关于这一块的内容,现将相关实现进行一个梳理。JS对粘贴板的访问有如下几种方式
- 原生方法
execCommand - 原生方法
Clipboard - 第三方库
clipboard.js(推荐)
经调研与实践,最终选取第三方库 clipboard.js 来实现自己的需求
document.execCommand()
已废弃:此功能已过时。 尽管它可能在某些浏览器中仍然有效,但不鼓励使用它,因为它可以随时被删除。 尽量避免使用它。
这是MDN文档给出的提醒,MDN文档甚至没有给出如何具体使用。
下面简单介绍一下execCommand的用法
<input type="text" id="input" value="123"><button onclick="copy()">copy</button><script>function copy() {const inputEle = document.querySelector('#input');inputEle.select();// 必须得由用户手动调用才能触发document.execCommand('copy');// cut、delete(删除选中元素) 同理// document.execCommand('cut');}</script>
copy、cut等命令会返回一个布尔值,确定浏览器此功能是否可用。
考虑到安全原因, document.execCommand(‘paste’)操作已经被禁止了。
如果想使用 execCommand 方法,又不想页面中出现可编辑区域,可以用下述办法取巧
<button onclick="copy2Clipboard('隐藏复制!!!')">copy</button><script>function copy2Clipboard(content) {const dom = document.createElement('input');dom.value = content;document.body.appendChild(dom);dom.select();document.execCommand('copy');document.body.removeChild(dom);};</script>
经调研,execCommand命令存在以下缺陷
- 不够灵活,只能操作
input,textarea或具有contenteditable属性的元素 execCommand是同步操作,如果复制/粘贴大量数据,页面会出现卡顿。有些浏览器还会跳出提示框,要求用户许可,这时在用户做出选择前,页面会失去响应。
Clipboard
剪贴板 Clipboard API 提供了响应剪贴板命令与异步读写系统剪贴板的能力。从权限 Permissions API 获取权限之后,才能访问剪贴板内容;如果用户没有授予权限,则不允许读取或更改剪贴板内容。
该 API 被设计用来取代使用document.execCommand()的剪贴板访问方式。
可用navigator.clipboard属性来检测浏览器是否支持该API,若返回undefined则不支持读取粘贴板
<button onclick="readClip()">readClip</button><script>function readClip() {// 读取文本navigator.clipboard.readText().then(clipText => console.log(clipText));// navigator.clipboard.read() 读取数据,比如图片}</script>
Chrome 浏览器规定,只有 HTTPS 协议的页面才能使用这个 API。不过,开发环境可正常使用
- 与粘贴板相关的权限有两个,
clipboard-write(写权限)和clipboard-read(读权限)。写权限”自动授予脚本,而“读权限”因为涉及到用户隐私,必须由用户明确同意授权。
可通过如下方式查看是否有相关读写权限
navigator.permissions.query({ name: 'clipboard-write' });
写入粘贴板
<button onclick="copy2clip()">copy2clip</button><script>function readClip() {// 写入文本navigator.clipboard.writeText("写入到粘贴板").then(() => console.log("成功写入剪贴板"));// navigator.clipboard.write 写入任意数据}</script>
clipboard.js库
复制文本到剪贴板的方法,没有flash,没有框架。 压缩后只有 3kb
安装
// node安装npm install clipboard --save// CDN引入<script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js"></script>
基础用法
复制/剪切 另外一个元素的文本
<!-- Target 提供复制的文本 --><input id="foo" value="https://github.com/zenorocha/clipboard.js.git"><!-- 支持复制其他元素内容 --><!-- <div id="foo">div元素</div> --><!-- 当存在多个target时,复制第一个 --><!-- Trigger 复制功能的触发器,触发器可以是其他元素,能够被点击就会被触发 --><!-- data-clipboard-target 设定target,语法同JQuerry --><button class="btn" data-clipboard-target="#foo">copy</button><!-- 通过设置 data-clipboard-action 属性将触发器变为剪切功能,共两个值,默认为copy --><!-- 只有可输入元素(input、textarea等)才支持剪切 --><button class="btn" data-clipboard-target="#foo" data-clipboard-action="cut">cut</button><script>// 查看浏览器是否支持clipboard 返回一个布尔值,// 如果不支持,你可以隐藏复制/剪切按钮。ClipboardJS.isSupported()// 对选中的元素进行监听,语法同JQuerryvar clipboard = new ClipboardJS('.btn');// 复制成功之后调用clipboard.on('success', function (e) {console.info('Action:', e.action);console.info('Text:', e.text);console.info('Trigger:', e.trigger);});// 复制失败之后调用clipboard.on('error', function (e) {console.error('Action:', e.action);console.error('Trigger:', e.trigger);});// 可以通过对这两个事件的监听为用户提供反馈</script>
复制自身属性的值
通过设置 data-clipboard-text属性使其复制自身
<button class="btn" data-clipboard-text="自身属性的内容">copySelf</button>
高级用法
动态设置target
需要返回一个DOM节点
<button class="btn" data-clipboard-target="#foo">copy</button><div>1234</div><script>var clipboard = new ClipboardJS('.btn', {// 将trigger的下一个兄弟节点作为target// 此时data-clipboard-targe属性不生效target: (trigger) => trigger.nextElementSibling});</script>
动态设置返回的文本
需要返回一个字符串
<button class="btn">copy</button><script>new ClipboardJS('.btn', {text: () => "动态文本内容"});</script>
设置容器
关于这一块自己也不是很理解有什么作用,现把官方解释翻译过来附在下面
要在 Bootstrap Modals 或任何其他更改焦点的库中使用,您需要将焦点元素设置为容器值。
new ClipboardJS('.btn', {container: document.getElementById('modal')});
清理创建的对象
如果你想更精确地管理 DOM 的生命周期,可以使用destroy方法清理创建的对象
clipboard.destroy();
清空剪切板内容
浏览器并没有提供可以清理剪切板的接口。如果网站在使用完剪切板内容后, 需要进行清理内容的话, 可以重新写入数据
// ...input.value = ' '; // input的值必须有值, 不能是空字符串input.select();document.execCommand('copy')// 或者使用clipboardnavigator.clipboard.writeText('');//new ClipboardJS('.btn', {text: () => " " // 必须有值, 不能是空字符串});
总结
document.execCommand用起来确实没那么舒服,甚至连官方都放弃它了,所以我们在日后的开发也应该尽量避免使用这个API,而尽量使用 Clipboard 这个API。
至于clipboard.js,虽然有依赖execCommand和Selection,但我个人用起来是没什么问题的,还是比较推荐的。
