前言
最近做了一个关于这方面的需求,自己也是第一次做关于这一块的内容,现将相关实现进行一个梳理。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()
// 对选中的元素进行监听,语法同JQuerry
var 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')
// 或者使用clipboard
navigator.clipboard.writeText('');
//
new ClipboardJS('.btn', {
text: () => " " // 必须有值, 不能是空字符串
});
总结
document.execCommand
用起来确实没那么舒服,甚至连官方都放弃它了,所以我们在日后的开发也应该尽量避免使用这个API,而尽量使用 Clipboard
这个API。
至于clipboard.js
,虽然有依赖execCommand
和Selection
,但我个人用起来是没什么问题的,还是比较推荐的。