grit

grit

Clipboard API:全新的异步复制、粘贴API

在 Safari 浏览器中直接使用 navigator.clipboard.writeText 是可以直接复制的,没有问题,但是如果在一个 promise 后使用 navigator.clipboard.writeText 就会报一个没有权限的错误,具体错误如下

Unhandled Rejection (NotAllowedError): The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.

原因:

  1. 因为开发中的复制内容是由接口请求的,safari 会拒绝此操作,由于安全限制,上述方法只能在用户与页面进行交互的情况下才能正常工作。如果您的复制操作不是由用户触发的(例如,通过定时器或其他非交互方式),则可能会受到浏览器的限制。
  2. 而 document.execCommand () 访问剪贴板是同步的,只能读写 DOM

Clipbo ard API#

全新的异步复制、粘贴 API。它提供(如果用户授予权限)对系统剪贴板内容的读取和写入访问权限。 Clipboard API 可用于在 Web 应用程序中实现剪切、复制和粘贴功能,只需调用 writeText 方法就可以成功复制一段文本。此 API 旨在取代使用document.execCommand访问剪贴板。

复制:将内容写入剪切板#

writeText()

将文本写入系统剪贴板,可以调用 writeText ()。此时文本已复制成功,可以使用 Ctrl+V 得到复制的内容。

async function copyText(text) {
  try {
    await navigator.clipboard.writeText(text)
    console.log('页面内容已复制到剪贴板 ')
  } catch (e) {
    console.log(`复制文案失败: ${e}`)
  }
}

write()

实际上,writeText () 只是通用 write () 方法的一种简写,它还允许您将图像复制到剪贴板。
图像复制成功后,需通过 read () 方法读取。
write () 方法接收参数为 ClipboardItem 对象数组。
创建一个新的 ClipboardItem 对象,需以 MIME 类型为键,以 Blob 为值。

目前未实现对多个 ClipboardItems 的支持。但支持多键值对的数据。

  const data = new ClipboardItem({
    // [MIME]: Blob
    'image/png': Blob,
    'text/plain': Blob
  })
  // 支持 
  await navigator.clipboard.write([data]);
  // 不支持
  await navigator.clipboard.write([data, data]);

注意:由于 Clipboard API 还属于实验性 API ,所以在 Safari 浏览器中表现有所不同.

  1. 必须在 https 环境才能调试使用。否则报错。NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.
  2. ClipbordItem 的 blob 属性值需要返回一个 Promise。
const data = new ClipboardItem({
  'text/plain': new Promise((resolve) => {
    resolve(new Blob(['example text'], { type: 'text/plain' }))
  })
})

粘贴:从剪切板读取数据#

readText()

要从剪贴板读取文本,可以调用 readText ()。

async function getClipboardText() {
  try {
    const text = await navigator.clipboard.readText();
    console.log(`粘贴内容: ${text}`);
    // 一些操作
  } catch (e) {
    console.error(`从剪切板获取数据失败: ${e}`);
  }
}

read()

read () 返回 ClipboardItems 对象的列表。要从剪贴板读取图像,可通过遍历 ClipboardItems 列表来获取。

async function getClipboardContents () {
  try {
    const clipboardItems = await navigator.clipboard.read() // clipboardItems列表
    for (const clipboardItem of clipboardItems) {
      // types: ClipboardItem 中可用的 MIME 类型数组。
      for (const type of clipboardItem.types) { 
        // 返回使用请求的 MIME 类型的 Blob 解析的 Promise。
        // 如果未找到 MIME 类型,则返回错误。
        const blob = await clipboardItem.getType(type) 
        if (type === 'text/plain') { // 文本
            // Blob 接口中的 text() 方法返回一个 Promise.
            // 该 Promise 使用包含 Blob 内容的字符串进行解析,解释为 UTF-8。
            const text = await blob.text()
            console.log(text)
          } else if (type === 'image/png') { // 图片
            const url = URL.createObjectURL(blob)
            console.log(url)
          }
      }
    }
  } catch (e) {
    console.error(`粘贴失败: ${e}` )
  }
}

监听事件#

Clipboard API 继承自 EventTarget (一个 DOM 接口,由可以接收事件、并且可以创建侦听器的对象实现),因此它也有监听事件。测试还未发现如何监听事件,目前可以使用之前的 document.addEventListener 监听。

document.addEventListener('paste', async (e) => {
  e.preventDefault();
  // 多内容或者图像内容
  getClipboardContents()
  
  // 当只有文本时
  if (navigator.clipboard) {
    text = await navigator.clipboard.readText();
  }
  else {
    text = e.clipboardData.getData('text/plain'); // 早期写法
  }
});

此文由 Mix Space 同步更新至 xLog
原始链接为 https://liu-wb.com/posts/default/clipboard


加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。