使用原生 Clipboard API 实现复制粘贴

621 阅读2分钟

「这是我参与2022首次更文挑战的第23天,活动详情查看:2022首次更文挑战

前言

前端的复制功能有很多种解决方案,常用的有document.execCommand()、插件clipboard.js、插件ZeroClipboard或者Clipboard API,今天我们就来了解一下Clipboard API 的使用。

介绍

插件 ZeroClipboard 的原理是利用 flash 来完成的,众所周知flash已经被淘汰了,所以这个插件也过时了。
document.execCommand() 是传统的操作剪贴板方法,各浏览器都支持,而Clipboard API 被设计用来取代使用 document.execCommand() 的剪贴板访问方式。 Clipboard API 的所有操作都是异步的,会返回Promise对象,不会造成页面卡顿,功能很强大,可以读取剪贴板的内容,还能读取和写入图片文件。

授权

在使用Clipboard API 前需要先进行授权,跟它有关的权限有两个clipboard-write(写权限)和clipboard-read(读权限),通过navigator.permissions的异步方法进行授权。clipboard-write会自动进行授予,而clipboard-read必须用户明确同意给予。也就是说,写入剪贴板,脚本可以自动完成,但是读取剪贴板时,浏览器会弹出一个对话框,询问用户是否同意读取。

const result = await navigator.permissions.query({ name: 'clipboard-read' });

返回的这个对象有一个 state 属性表面授权情况,他有三个值granted、denied、prompt,如果是 denied 代表拒绝授权。也可以通过浏览器设置查看权限情况,我们这里以Chrome 为例

image.png

使用

读取剪贴板内容

使用异步方法readText可以读取剪贴板内容

(async () => {
  const text = await navigator.clipboard.readText();
  console.log(text);
})();

除了文字的读取,我可以使用 read方法读取剪贴板图片

(async () => {
    const clipboardItems = await navigator.clipboard.read();
    for (const clipboardItem of clipboardItems) {
      for (const type of clipboardItem.types) {
        const blob = await clipboardItem.getType(type);
        console.log(URL.createObjectURL(blob));
      }
    }
})();

写入剪贴板

使用异步方法writeText,进行文字的写入操作。

(async () => {
  await navigator.clipboard.writeText('写入数据');
  console.log('写入完成');
})();

使用write可以写入文件

const imgURL = '图片地址';
const data = await fetch(imgURL);
const blob = await data.blob();
await navigator.clipboard.write([
  new ClipboardItem({
    [blob.type]: blob
  })
]);
console.log('Image copied.');

总结

Clipboard API 功能比document.execCommand()强大,但是因为需要授权,所以无法做到无感知的复制。正常复制文案的话使用document.execCommand()就足够了,一些需要复制写入图片文件的情况下使用它比较合适。