一个小小的诀窍。实现主题的复制代码功能时,思路刚好和这篇文章差不多,不过这篇文章的代码要更加合理。

本文将会深入介绍 30 秒代码copyToClipboard 代码块的工作原理。你可以在项目仓库中找到它的源代码以及更多其他的实用方法。

30 秒代码:可以在 30 秒或更短时间内理解的 JavaScript 代码块

核心功能

搭建网站时经常会遇到一个需求,那就是在用户没有选中或者使用键盘组合键的情况下,复制文本到剪贴板。JavaScript 可以用短短五步轻松解决这个问题:

1.创建一个稍后将插入到文档中的 <textarea> 元素。将我们想要复制到剪贴板的字符串设置为它的 value
2.将上诉 <textarea> 元素插入到当前的 HTML 文档中。
3.使用 HTMLInputElement.select() 选中 <textarea> 元素的内容。
4.使用 Document.execCommand('copy') 复制 <textarea> 元素的内容到剪贴板。
5.从文档中移除 <textarea> 元素。

这个方法的最简版本大概如下:

const copyToClipboard = str => {
  const el = document.createElement('textarea');
  el.value = str;
  document.body.appendChild(el);
  el.select();
  document.execCommand('copy');
  document.body.removeChild(el);
};
copyToClipboard 方法的基本实现

记住,这个方法不是在任何情况下都可以使用的。因为 Document.execCommand() 的工作方式,它必须作为用户操作的响应结果。

让插入的元素不可见

如果你试用了上面的方法,你可能会在 <textarea> 元素插入或者移除时看到闪烁。这对使用屏幕阅读器的人来说很糟糕,因为它会导致一些非常烦人的问题。因此,下一步合理的操作就是使用 CSS 让元素不可见,同时设置只读,以防止用户的试图干扰。

const copyToClipboard = str => {
  const el = document.createElement('textarea');
  el.value = str;
  el.setAttribute('readonly', '');
  el.style.position = 'absolute';
  el.style.left = '-9999px';
  document.body.appendChild(el);
  el.select();
  document.execCommand('copy');
  document.body.removeChild(el);
};
隐藏文本域的 copyToClipboard 实现

保存和恢复原先的文档选中

最后需要考虑的问题是,用户可能已经在 HTML 文档中选中了一些内容,明智之举是不移除他们选中的这些内容。幸运的是,我们可以使用诸如 DocumentOrShadowRoot.getSelection(),Selection.rangeCount, Selection.getRangeAt(), Selection.removeAllRanges()Selection.addRange() 等现成的 JavaScript 方法和属性来保存和恢复原先的文档选中。这是最终的带注释的改良代码:

const copyToClipboard = str => {
  const el = document.createElement('textarea');  // 创建一个 <textarea> 元素
  el.value = str;                                 // 设置它的值为你想复制的字符串
  el.setAttribute('readonly', '');                // 设置为只读以防止干扰
  el.style.position = 'absolute';                 
  el.style.left = '-9999px';                      // 移出屏幕外以使其不可见
  document.body.appendChild(el);                  // 插入 <textarea> 元素到 HTML 文档中
  const selected =            
    document.getSelection().rangeCount > 0        // 检查是否之前曾选中过内容
      ? document.getSelection().getRangeAt(0)     // 如果找到,则保存选中
      : false;                                    // 标记为  false 以表示不存在之前选中的内容
  el.select();                                    // 选中 <textarea> 的内容
  document.execCommand('copy');                   // 复制 - 仅当作为用户操作的响应结果时才可以工作(比如,点击事件)
  document.body.removeChild(el);                  // 移除 <textarea> 元素
  if (selected) {                                 // 如果在复制前已存在选中的内容
    document.getSelection().removeAllRanges();    // 取消 HTML 文档中所有的选中部分
    document.getSelection().addRange(selected);   // 恢复原来的选中
  }
};
最终形式的 copyToClipboard,可以保存选中

这就是全部的内容。仅用了不到 20 行代码,我们已经创建了前端开发中最常用的方法之一。

如果喜欢这篇文章,给一个 clap(或者 fifty)。记得查看 30 秒代码 ,为你的 JavaScript 项目找到更多实用的代码块!