夜间模式CodeSnippetStyle:
日间模式CodeSnippetStyle:

0%


Click To Copy 的实现 [2/2] JavaScript实现复制内容到前切板

在过去的几年,浏览器都一般使用document.execCommand来进行剪切板操作。诚然,有这样一个单独且被广泛支持的方式去完整的复制和粘贴内容到Web应用是很帮的,但是,这种方式是有一定代价的:剪切板访问是同步的,并且,由于通常是操作用于input元素,因此只能进行DOM的读写操作。

这些问题,如果是在复制粘贴少量字节的文本内容时,同步访问是不会有多大影响的。但是同步访问会导致在很多情况下造成页面阻塞。在内容被安全粘贴之前,还需要时间去净化,解码。如果浏览器需要加载自粘贴内容的外链资源,那么有可能会因为磁盘读取和网络问题带来页面阻塞。试想,如果混入权限,询问用户能否在访问剪切板的时候阻塞页面会怎么样呢?

同时,在使用document.execCommand进行剪切板访问操作的时候,交互的权限定义是非常松散的,并且会因为浏览器的不同有所区别。因此,想象,如果专用的剪切板API解决了页面阻塞和权限问题会是什么样呢?

这就是 Async Clipboard API,(异步前切板API),该方案在Chrome66中被退出,提供了很好的权限模型定义,并且由于异步特点不会阻塞页面。

复制:写入文本至剪切板(Copy: writing text to the clipboard)

通过调用writeText()可以实现复制文本到剪切板,由于该API是异步执行的,writeText()方法会返回一个Promise用于处理resolved或者rejected,这取决于传入的文本是否被正常传入。

navigator.clipboard.writeText('Text to be copied')
  .then(() => {
    console.log('Text copied to clipboard');
  })
  .catch(err => {
    // This can happen if the user denies clipboard permissions:
    console.error('Could not copy text: ', err);
  });

类似的,你可以将该过程写做一个异步函数( async function

async function copyPageUrl() {
  try {
    await navigator.clipboard.writeText(location.href);
    console.log('Page URL copied to clipboard');
  } catch (err) {
    console.error('Failed to copy: ', err);
  }
}

粘贴:从剪切板读出文本(Paste:reading)

这个过程和复制很想,你可以通过调用readText()来剪切剪切板中的文本。并且等待返回的Promise来resolve,或者reject。

navigator.clipboard.readText()
  .then(text => {
    console.log('Pasted content: ', text);
  })
  .catch(err => {
    console.error('Failed to read clipboard contents: ', err);
  });

为了保持一致,这是等效的异步函数:

async function getClipboardContents() {
  try {
    const text = await navigator.clipboard.readText();
    console.log('Pasted content: ', text);
  } catch (err) {
    console.error('Failed to read clipboard contents: ', err);
  }
}

处理粘贴事件(Handling paste events)

已经计划引入一个新事件来检测剪贴板的变化,但是目前最好使用“粘贴”事件。 它与用于读取剪贴板文本的新异步方法很好地结合在一起:

document.addEventListener('paste', event => {
  event.preventDefault();
  navigator.clipboard.readText().then(text => {
    console.log('Pasted text: ', text);
  });
});

安全和权限(Security and permissions)

剪贴板访问一直是浏览器的安全隐患。没有适当的权限,页面可以静默的复制所有的恶意内容到用户的剪切板,在用户粘贴的时候,将产生灾难性的结果。想象一个网页静默的复制 rm -rf / 或者减压炸弹图片(decompression bomb image)到你的剪切板。

让网页不受限制地访问剪贴板就更麻烦了。

用户通常会将密码和个人信息等敏感信息复制到剪贴板上,这样任何页面都可以在用户不知情的情况下读取这些信息。

和很多新的API一样,navigator.clipboard仅仅支持通过HTTPS协议部署的页面,这样能够有效阻止滥用,仅当页面是活动选项卡时才允许剪贴板访问,处于活动选项卡中的页面可以在不请求权限的情况下写入剪贴板,但从剪贴板读取始终需要权限。

为了使事情变得简单,将两个新的复制和粘贴权限添加到了权限API(Permissions API

当页面为活动选项卡时,将自动向页面授予剪贴板写入权限。 必须请求剪贴板读取权限,您可以通过尝试从剪贴板读取数据来完成。

{ name: 'clipboard-read' }
{ name: 'clipboard-write' }

与使用Permissions API进行的所有操作一样,可以检查您的应用是否具有与剪贴板进行交互的权限:

navigator.permissions.query({
  name: 'clipboard-read'
}).then(permissionStatus => {
  // Will be 'granted', 'denied' or 'prompt':
  console.log(permissionStatus.state);

  // Listen for changes to the permission state
  permissionStatus.onchange = () => {
    console.log(permissionStatus.state);
  };
});

向后看(Looking back)

在介绍Async Clipboard API之前,各浏览器有一些不同的复制粘贴操作的混合实现。

在大多数浏览器中,浏览器自身的复制粘贴能够通过使用document.execCommand('copy')document.execCommad('paste')来触发,如果被复制的文本是一个不在DOM中的字符串。我必须注入并选择它:参考[Click To Copy 的实现 [1/2] JavaScript实现复制内容到前切板]

检测和备用方案(Detection and fallback)

检测浏览器是否支持Async Clipboard API 操作 paste,如果不支持则采用替代方案,以防止报错。

document.addEventListener('paste', async e => {
  let text;
  if (navigator.clipboard) {
    text = await navigator.clipboard.readText()
  }
  else {
    text = e.clipboardData.getData('text/plain');
  }
  console.log('Got pasted text: ', text);
});

阅读原文

posted @ 2020-08-11 10:19  暮冬有八  阅读(493)  评论(1编辑  收藏  举报
BACK TO TOP

😀迷海无灯听船行。Github WeChat