解锁剪贴板访问

解锁剪贴板访问


1、document.execCommand() 方法说明

在 IE10 以前我们可以使用 document.execCommand() 来实现文本的复制和粘贴操作,但是这种粘贴板是同步操作的。

这样页面在复制较少内容的时候页面不会出现卡顿的情况,但是当你的复制粘贴的内容中带有图片、文本和外部链接的时候,浏览器会对复制的内容进行清理和图片的解码操作,这样就会导致磁盘或者网络的阻塞,从而导致页面产生卡顿情况。

document.execCommand() 的权限采用松散的定义,这样导致了在不同浏览器之间存在兼容性的问题。所以现在这个比较新的浏览器中都已废弃这个 API。

2、Clipboard 说明

clipboard 接口实现了 Clipboard API,如果用户授予了相应的权限后就能够使用系统剪贴板的读写操作。

所有的 clipboard api 的方法都是异步的,即返回的都是 Promise 对象,在剪贴板访问成功后就可以进行相应操作,但是剪贴板拒绝返回的话,promise 就会返回错误信息回来。

clipboard 相关的方法有如下 4 个:

  • read()
    从剪贴板读取数据(文本和图片),返回一个 Promise 对象。在检索到数据后,就会返回一个 clipboardItem 对象数组。

  • readText()
    从剪贴板中读取文本数据,返回一个 Promise 对象。在检索到数据后就会返回一个字符串。

  • write()
    写入任何数据到粘贴板中,是一个异步操作,当操作完成后会返回一个 Promise 对象。这个方法需要事先把需要复制的内容转为 blob,并且传入的参数是 ClipboardItem 的实例对象数组。ClipboardItem 主要是存放 bolob 数据。

  • writeText()
    写入一个文本到粘贴板中,是一个异步操作,当操作完成后会返回一个 Promise 对象。

注意:火狐浏览器虽然支持 Clipboard 这个 API,但是它提供的方法只有writeText()

3、writeText() / write() 实例演示

const _copyBtn = document.getElementById("copy_btn");

async function copyPageInfo() {
  const _textArea = document.getElementById("copy_box");
  try {
    await navigator.clipboard.writeText(_textArea.value);
    console.log("复制成功");
  } catch (error) {
    console.log(error);
  }
}

_copyBtn.addEventListener("click", () => {
  copyPageInfo();
});
const _copy_img_btn = document.getElementById("copy_img_btn");

async function copyPageImg() {
  const _imgUrl = "./images/grid布局1.png";
  const data = await fetch(_imgUrl);
  const blob = await data.blob();
  try {
    await navigator.clipboard.write([
      new ClipboardItem({
        [blob.type]: blob,
      }),
    ]);
    console.log("图片复制成功");
  } catch (error) {
    console.log(error);
  }
}

_copy_img_btn.addEventListener("click", () => {
  copyPageImg();
});

4、readText() / read() 实例演示

const _readText = document.getElementById("readText");

async function getTextData() {
  try {
    const text = await navigator.clipboard.readText();
    console.log(text);
  } catch (error) {
    console.log(error);
  }
}

_readText.addEventListener("click", () => {
  getTextData();
});
const _readImg = document.getElementById("readImg");

async function getImgData() {
  try {
    const _clipboardItem = await navigator.clipboard.read();
    for (const item of _clipboardItem) {
      for (const type of item.types) {
        const blob = await item.getType(type);
        console.log(URL.createObjectURL(blob));
      }
    }
  } catch (error) {
    console.log(error);
  }
}

_readImg.addEventListener("click", () => {
  getImgData();
});

5、复制事件/张贴事件

5.1 复制事件

可以使用 copy 事件来进行复制事件的监听,因为 copy 包含 clipboardData 属性,其中的项目已经采用正确的格式,从而无需手动创建 Blob。

具体实例如下:

document.addEventListener("copy", async (e) => {
  e.preventDefault();
  try {
    let clipboardItems = [];
    for (const item of e.clipboardData.items) {
      if (!item.type.startsWith("image/")) {
        continue;
      }
      clipboardItems.push(
        new ClipboardItem({
          [item.type]: item,
        })
      );
      await navigator.clipboard.write(clipboardItems);
      console.log("Image copied.");
    }
  } catch (err) {
    console.error(err.name, err.message);
  }
});

5.2 张贴事件

可以使用 paste 事件来进行张贴事件的监听。具体实例代码如下:

document.addEventListener("paste", async (e) => {
  e.preventDefault();
  const text = await navigator.clipboard.readText();
  console.log("Pasted text: ", text);
});

6、安全和权限

ClipBoard API 仅支持通过 HTTPS 提供的页面。为帮助防止滥用,仅当页面是活动选项卡时才允许访问剪贴板。活动选项卡中的页面无需请求许可即可写入剪贴板,但从剪贴板读取始终需要许可。

ClipBoard API 的异步特性真正派上用场的地方在于:如果尚未授予权限,尝试读取或写入剪贴板数据的操作会自动提示用户授予权限。由于 API 是基于承诺的,这是完全透明的,用户拒绝剪贴板权限会导致承诺拒绝,因此页面可以做出适当的响应。

当页面处于活动标签页时,会自动授予 clipboard-write 权限。必须请求 clipboard-read 权限,这在您尝试从剪贴板读取数据时需要执行。例如如下的授权验证代码:

async function check() {
  const queryOpts = { name: "clipboard-read", allowWithoutGesture: false };
  const permissionStatus = await navigator.permissions.query(queryOpts);
  // 可以获取到 'granted', 'denied' or 'prompt':
  console.log(permissionStatus.state);

  // 监听粘贴板的状态改变
  permissionStatus.onchange = () => {
    console.log(permissionStatus.state);
  };
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值