介绍
“一键复制”功能是前端开发中常见的功能需求之一,在链接复制、图片分享等场景下可以简化操作流程,极大的提升用户体验。
思路
在浏览器中,主要是利用 JavaScript 实现对剪贴板的写入和读取操作,来实现对内容的复制和粘贴。
方案
在页面中添加 input 和 button 这两个 DOM 元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<input type="text" value="我是要被拷贝的文字" />
<button>copy</button>
</body>
</html>
所要达到的目的就是通过点击 copy 按钮可以将 input 中的内容写入到 剪切板,然后执行 粘贴(ctrl+v) 操作时可以将其内容写入到可输入的控件中去,下面是几种常见的实现方案:
1. document.execCommand
const input = document.querySelector("input");
const button = document.querySelector("button");
button.addEventListener("click", () => {
input.select();
document.execCommand("copy");
});
通过 input.select() 选中 input 中的文本,接着执行 document.execCommand(“copy”) 将内容写入到剪切板,接着只要快速粘贴即可。
作为操作剪切板的传统方法,虽然使用简便,操作单一,但现阶段已被弃用,即使一些浏览器会出于 兼容性 的目的进行保留。
原因如下:
- 仅可将选中的数据进行 copy,无法便捷的写入自定义的内容
- 该方法输入 同步 操作,并且需要操作 DOM,在一定程度上会影响页面渲染和脚本执行
- 无需用户进行 授权,如果涉及敏感数据,可能存在极大的安全隐患
2. Clipboard API
该 API 被设计用来取代使用 document.execCommand() 的剪贴板访问方式,提供了响应剪贴板命令(剪切、复制和粘贴)与异步读写系统剪贴板的能力。从权限 Permissions API(en-US) 获取权限之后,才能访问剪贴板内容;如果用户没有授予权限,则不允许读取或更改剪贴板内容。
const clipboard = navigator.clipboard
使用 navigator.clipboard 获取 clipboard Object,如果值为 undefined,则说明浏览不支持。
如果想要往剪切板中写入内容,可以使用 writeText 方法
const clipboard = navigator.clipboard;
if (!clipboard) {
console.log("不支持");
return
}
const button = document.querySelector("button");
button.addEventListener("click", async () => {
try {
await clipboard.writeText("自定义的文本内容");
console.log("success");
} catch (error) {
console.log("failed", error);
}
});
通过 clipboard.writeText 方法写入自定义的文本内容后执行粘贴操作即可。
如果想要粘贴剪切板中内容,可以使用 readText 方法
const clipboard = navigator.clipboard;
if (!clipboard) {
console.log("不支持");
return
}
const button = document.querySelector("button");
button.addEventListener("click", async () => {
try {
const text = await clipboard.readText();
console.log("success", text);
} catch (error) {
console.log("failed", error);
}
});
假设事先已经通过 ctrl+v 拷贝过一些内容,或者说通过 writeText 方法写入过一些内容到剪切板,此时点击 copy 按钮,就会通过 clipboard.readText 读取剪切板的内容,如果是首次读取,则浏览器会弹出权限弹窗提醒用户进行授权,授权成功即可读取出剪切板中的内容并打印在控制台。
通过授权提示可以发现,clipboard 实际上也是支持读取和写入图片数据的,如果想要写入图片数据,需要使用 write 方法
const clipboard = navigator.clipboard;
if (!clipboard) {
console.log("不支持");
}
const button = document.querySelector("button");
button.addEventListener("click", async () => {
try {
const imgblob = await (
await fetch("https://dummyimage.com/100.png")
).blob();
await clipboard.write([
new ClipboardItem({
"image/png": imgblob,
}),
]);
console.log("success");
} catch (error) {
console.log("failed", error);
}
});
代码还是比较简单的,拿到图片的 blob 对象之后,当作 new ClipboardItem 的参数进行传入再通过 write 写进剪切板,接着可以随便打开一个聊天软件执行粘贴操作即可。
如果说你想读取已经写入到剪切板中的图片数据,可以使用 read 方法
const clipboard = navigator.clipboard;
if (!clipboard) {
console.log("不支持");
}
const button = document.querySelector("button");
button.addEventListener("click", async () => {
try {
const imgblob = await (
await fetch("https://dummyimage.com/100.png")
).blob();
await clipboard.write([
new ClipboardItem({
"image/png": imgblob,
}),
]);
// 读取已经写入到剪切板中的数据
const clipboardItemList = await clipboard.read();
clipboardItemList.forEach((i) => {
i.types.forEach(async (t) => {
const iBlob = await i.getType(t);
console.log("iBlob", iBlob);
});
});
console.log("success", clipboardItemList);
} catch (error) {
console.log("failed", error);
}
});
为了与 Google Chrome 浏览器保持一致,Firefox 只允许此函数处理 文本、HTML 和 PNG 数据;在使用前需要检查 浏览器兼容性 和 剪切板可用性 以获取更多兼容性的信息。
可以看到,在 Clipboard API 的使用上,所有操作都返回了 Promise 对象,这意味着这些操作都是 异步 的;在 read 操作发生时,还会提示用户进行授权,否则会处理失败;除此之外,该功能仅在支持浏览器的安全上下文(HTTPS)中可用,开发环境(localhost)除外。
3. clipboard.js
cliboard.js 是一个轻量级的 clipboard 库,用于简化在网页中执行剪贴板操作的过程。
它提供了一种简单而强大的方式,让开发者能够通过点击按钮或其他交互方式,将文本内容复制到剪贴板,或从剪贴板中粘贴文本。
原文链接:https://juejin.cn/post/7327686118887440396 作者:coderMonkey