简言
记录下利用js使用剪切板的方法。
Clipboard API
剪贴板 Clipboard API 提供了响应剪贴板命令(剪切、复制和粘贴)与异步读写系统剪贴板的能力。
该 API 被设计用来取代使用 document.execCommand() 的剪贴板访问方式。
这个api比较新,所以兼容性比较差
Clipboard
Clipboard 接口实现了 Clipboard API,如果用户授予了相应的权限,其就能提供系统剪贴板的读写访问能力。
系统剪贴板暴露于全局属性 Navigator.clipboard 之中。
他有四个方法:
- read() — 从剪贴板读取数据(比如图片),返回一个 Promise 对象。在检索到数据后,promise 将兑现一个 ClipboardItem (en-US) 对象的数组来提供剪切板数据。
- readText() — 从操作系统读取文本;返回一个 Promise,在从剪切板中检索到文本后,promise 将兑现一个包含剪切板文本数据的 DOMString。
- write() — 写入任意数据至操作系统剪贴板。这是一个异步操作,在操作完成后,返回的 promise 的将被兑现。
- writeText() — 写入文本至操作系统剪贴板。返回一个 Promise,在文本被完全写入剪切板后,返回的 promise 将被兑现。
write的兼容性比read兼容性好一些。
由于兼容性比较差,所以在失败时注意实现补救措施。
示例
使用的话比较简单,需要navigator.clipboard 全局属性。
navigator.clipboard.writeText('hello world').then(() => {
console.log('复制成功')
}, () => {
console.log('拒绝复制');
})
读取有个注意点,需要该文档聚焦才能读取到剪切板内容,简单办法就是使用一个按钮触发读取剪切板操作。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Navigator.clipboard</title>
</head>
<body>
<h1>navigator.clipboard</h1>
<button id="btn">读取剪切板</button>
<script>
const Clipboard = navigator.clipboard
Clipboard.writeText('hello world').then(() => {
console.log('复制成功')
}, () => {
console.log('拒绝复制');
})
document.getElementById("btn").addEventListener("click", function () {
Clipboard.readText().then(res => {
console.log(res, '结果');
})
}
)
</script>
</body>
</html>
document.execCommand
当一个 HTML 文档切换到设计模式时,document暴露 execCommand 方法,该方法允许运行命令来操纵可 编辑内容区域(contenteditable为true)的元素。
虽然这个方法被弃用了,但是比上面的兼容性更好。
语法
bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)
返回值一个 Boolean ,如果是 false 则表示操作不被支持或未被启用。
参数:
-
aCommandName
一个 DOMString ,命令的名称。可用命令列表请参阅 命令列表-MDN -
aShowDefaultUI
一个 Boolean,是否展示用户界面,一般为 false。Mozilla 没有实现。 -
aValueArgument
一些命令(例如 insertImage)需要额外的参数(insertImage 需要提供插入 image 的 url),默认为 null。
aCommandName 有 copy、cut命令所以,可以进行复制剪切操作。
示例
document.execCommand()在执行操作之前,需要选中可操作编辑内容区域,你可以使用selection API 和 Range API创建选中区域。
简单办法就是,新建一个textarea元素,然后利用select()方法快速选中内容:
const textarea = document.createElement('textarea') as HTMLTextAreaElement
// 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域
textarea.readOnly = true
textarea.style.position = 'absolute'
textarea.style.left = '-9999px'
// 指定内容
textarea.value = 'hello world'
// 将 textarea 插入到 body 中
document.body.appendChild(textarea)
// 选中值并复制
textarea.select()
const result = document.execCommand('Copy')
if(result){
console.log('success')
}
//删除textarea元素
document.body.removeChild(textarea)
利用copy、cut等剪切板事件
例如,当用户通过浏览器的用户界面发起复制动作时,将触发 copy 事件,该事件的默认行为是将当前选中的内容(如有)复制到系统剪贴板。
事件处理器可以通过调用 ClipboardEvent.clipboardData 属性上的 setData(format, data) 修改剪贴板内容,并通过 event.preventDefault() 取消默认行为。
然而,事件处理器不可以读取剪贴板数据。
示例
const source = document.querySelector("div.source");
source.addEventListener("copy", (event) => {
const selection = document.getSelection();
// 改变要复制到剪切板的内容
event.clipboardData.setData("text/plain", selection.toString().toUpperCase());
event.preventDefault();
});
可以实现拒绝复制,或者复制内容添加标识等操作。
结语
Clipboard API不能用时,可以使用document.execCommand()方法,若两者都不可以使用,可以考虑引导用户手动复制。