在React中用剪贴板API实现复制到剪贴板的功能

3,168 阅读5分钟

如果你正在阅读这篇博文,很有可能你已经从GitHub上克隆了一个git仓库。GitHub 在其网站上增加了一个小而强大的功能,允许用户点击一个按钮,将 Git 的 URL 复制到剪贴板上,这样你就可以轻松地将其粘贴到终端,将仓库克隆到本地机器上。

这比选择整行文字,然后点击Control+CCommand+C 来复制它要容易得多。它还可以防止你在选择URL时遗漏任何字符。

现在,假设你正在为自己建立一个新的博客网站,你想让读者尽可能容易地与人分享一篇文章。一些社交媒体网站提供了使用链接并在其网站上自动开始发表新文章的方法,但不是每个应用程序都支持这种功能。

如果你想复制一个URL并通过Zoom或iMessage发送给某人,怎么办?如果我们给用户一个按钮来复制文本,这将大大改善用户体验。这对移动用户来说也会特别有帮助。

在这篇文章中,我将向你展示如何通过创建一个可重复使用的React组件来实现这一目标,该组件将接受文本作为一个道具值,并且在点击时,将文本复制到用户的剪贴板。

什么是JavaScript剪贴板API?

值得庆幸的是,在现代网络开发时代,我们得到了许多有用的网络API,使在浏览器中复制和粘贴文本等任务变得简单。目前用于剪贴板交互的事实上的API是剪贴板API,它提供了一些简单的函数来调用,以便将文本复制到用户的剪贴板上并从其中读取项目。

不幸的是,并不是所有的网络浏览器都支持这个API,你可能能猜到是哪一个。是Internet Explorer。如果你仍然要支持IE,有一个传统的函数可以作为备份,使用document.execCommand('copy')

这里有一个函数的例子,它接受文本作为参数并将其复制到用户的剪贴板上。

export async function copyTextToClipboard(text) {
  if ('clipboard' in navigator) {
    return await navigator.clipboard.writeText(text);
  } else {
    return document.execCommand('copy', true, text);
  }
}

现在,让我们来看看这个。

首先,我们有一个异步函数叫copyTextToClipboard ,它有一个单一的参数text。它检查navigator 对象上是否存在剪贴板这个属性。这是一个检查当前浏览器是否支持剪贴板API的简单方法。

接下来,如果浏览器支持剪贴板API,我们将等待承诺navigator.clipboard.writeText(text) ,并将其返回。

否则,我们调用Document.execCommand 函数,参数为'copy', true, text 。你可以在MDN文档中阅读关于这个命令的参数。

当你在浏览器中运行这个命令时,它将把作为参数传入的任何文本复制到用户的剪贴板上,这样,当用户粘贴文本时,它就会出现。

现在我们有了一个简单的工作函数,我们要把它实现在一个灵活的React组件中。

在React中使用剪贴板API

让我们先建立一个简单的React组件,直观地表示我们要实现的东西。

function ClipboardCopy({ copyText }) {
  const [isCopied, setIsCopied] = useState(false);

  // TODO: Implement copy to clipboard functionality

  return (
    <div>
      <input type="text" value={copyText} readOnly />
      <button>
        <span>{isCopied ? 'Copied!' : 'Copy'}</span>
      </button>
    </div>
  );
}

在这里,我设置了组件ClipboardCopy ,它接受了属性copyText 。这将是我们希望我们的用户复制的文本。它将呈现一个只读的<input> 元素,显示我们的copyText 字符串和一个按钮,我们将用它来执行我们的复制功能。

我还添加了状态值isCopied ,以跟踪文本是否被复制到剪贴板,并改变我们的copy 按钮上显示的文本。

现在,我们需要为我们的按钮创建一个onClick 处理函数,它将异步调用我们的copyToClipboard 函数,并传递copyText, 作为参数。

根据函数的结果,我们将把isCopied 的状态改为true ,或者,如果发生错误,我们将把它打印到控制台。如果命令成功,当用户下次在他们的设备上粘贴文本时,copyText 的值将是结果。

function ClipboardCopy({ copyText }) {
  const [isCopied, setIsCopied] = useState(false);

  // This is the function we wrote earlier
  async function copyTextToClipboard(text) {
    if ('clipboard' in navigator) {
      return await navigator.clipboard.writeText(text);
    } else {
      return document.execCommand('copy', true, text);
    }
  }

  // onClick handler function for the copy button
  const handleCopyClick = () => {
    // Asynchronously call copyTextToClipboard
    copyTextToClipboard(copyText)
      .then(() => {
        // If successful, update the isCopied state value
        setIsCopied(true);
        setTimeout(() => {
          setIsCopied(false);
        }, 1500);
      })
      .catch((err) => {
        console.log(err);
      });
  }

  return (
    <div>
      <input type="text" value={copyText} readOnly />
      {/* Bind our handler function to the onClick button property */}
      <button onClick={handleCopyClick}>
        <span>{isCopied ? 'Copied!' : 'Copy'}</span>
      </button>
    </div>
  );
}

我在这里添加的是一个新函数,handleCopyClick ,它作为我们的按钮元素的onClick 事件处理程序。

当用户点击按钮时,事件处理函数被执行,而我们的异步函数copyTextToClipboard 被执行。

一旦该函数被解决,它或者将isCopied 状态值设置为true ,或者,如果发生错误,则打印出错误。

我还添加了一个setTimeout 函数,在1.5秒后将复制的状态值重置回false 。这允许我们给用户一些交互反馈,因为将文本复制到剪贴板是一个 "背景任务",不提供任何内在的反馈。

现在,我们可以在React应用程序的任何地方使用这个组件,就像这样。

function App() {
  return (
    <div className="App">
      <ClipboardCopy copyText="https://google.com" />
      <ClipboardCopy copyText="https://logrocket.com" />
    </div>
  );
}

最后,当你运行该应用时,这就是你的用户应该看到的东西。

Copy Button Next To Link Being Pressed

你可以通过在调用copyTextToClipboard ,在出现错误的情况下提供更好的反馈来改进这个方案。如果你的项目中有一个错误组件,你可以调用一个函数或改变状态来向用户显示一个错误,而不是向控制台打印文本,用户很可能永远不会看到。

总结

现在我们已经介绍了JavaScript剪贴板API,你可以看到在你的任何用例中实现它是多么容易。这也大大提高了你网站的用户体验。当然,如果你想为你的内容获得观众,让用户简单地分享你的内容也可以增加你的网站曝光率。读完这篇文章后,希望你能为自己收获这些好处。

The postImplementing copy-to-clipboard in React with Clipboard APIappeared first onLogRocket Blog.