我使用的是ReactJS,当用户点击一个链接时,我想复制一些文本到剪贴板。

我使用Chrome 52,我不需要支持任何其他浏览器。

我不明白为什么这段代码没有导致数据被复制到剪贴板。(代码片段的来源是Reddit的一篇帖子)。

我做错了吗?谁能建议有一个“正确”的方法来实现复制到剪贴板使用reactjs?

copyToClipboard = (text) => {
  console.log('text', text)
  var textField = document.createElement('textarea')
  textField.innerText = text
  document.body.appendChild(textField)
  textField.select()
  document.execCommand('copy')
  textField.remove()
}

当前回答

使用材质UI完全工作的React组件

为了更好地理解,我还准备了一个CodeSandbox。希望这能有所帮助。

import { useState } from "react";
import { IconButton, Snackbar } from "@mui/material";
import ShareIcon from "@mui/icons-material/Share";

const CopyToClipboardButton = () => {
  const [open, setOpen] = useState(false);

  const handleClick = () => {
    setOpen(true);
    navigator.clipboard.writeText(window.location.toString());
  };

  return (
    <>
      <IconButton onClick={handleClick} color="primary">
        <ShareIcon />
      </IconButton>
      <Snackbar
        message="Copied to clibboard"
        anchorOrigin={{ vertical: "top", horizontal: "center" }}
        autoHideDuration={20000}
        onClose={() => setOpen(false)}
        open={open}
      />
    </>
  );
};

export default CopyToClipboardButton;

下面是按钮的样子:

当你点击它时:

来源:https://fwuensche.medium.com/react——按钮——复制到剪贴板- 75 ef5ecdc708

其他回答

对于那些试图从DIV而不是文本字段中进行选择的人,下面是代码。代码是不言自明的,但如果你想了解更多信息,请在这里评论:

     import React from 'react';
     ....

    //set ref to your div
          setRef = (ref) => {
            // debugger; //eslint-disable-line
            this.dialogRef = ref;
          };

          createMarkeup = content => ({
            __html: content,
          });

    //following function select and copy data to the clipboard from the selected Div. 
   //Please note that it is only tested in chrome but compatibility for other browsers can be easily done

          copyDataToClipboard = () => {
            try {
              const range = document.createRange();
              const selection = window.getSelection();
              range.selectNodeContents(this.dialogRef);
              selection.removeAllRanges();
              selection.addRange(range);
              document.execCommand('copy');
              this.showNotification('Macro copied successfully.', 'info');
              this.props.closeMacroWindow();
            } catch (err) {
              // console.log(err); //eslint-disable-line
              //alert('Macro copy failed.');
            }
          };

              render() {
                    return (
                        <div
                          id="macroDiv"
                          ref={(el) => {
                            this.dialogRef = el;
                          }}
                          // className={classes.paper}
                          dangerouslySetInnerHTML={this.createMarkeup(this.props.content)}
                        />
                    );
            }

你的代码应该工作完美,我用同样的方式。只需要确保如果click事件是从弹出屏幕中触发的,比如bootstrap模式或其他,创建的元素必须在该模式中,否则它不会被复制。您总是可以给出该模式中元素的id(作为第二个参数),并使用getElementById检索它,然后将新创建的元素附加到该元素而不是文档。就像这样:

copyToClipboard = (text, elementId) => {
  const textField = document.createElement('textarea');
  textField.innerText = text;
  const parentElement = document.getElementById(elementId);
  parentElement.appendChild(textField);
  textField.select();
  document.execCommand('copy');
  parentElement.removeChild(textField);
}

导航器。剪贴板不工作在HTTP连接根据他们的文档。所以你可以检查它是否未定义,并使用document.execCommand('copy')来代替,这个解决方案应该涵盖几乎所有的浏览器

const defaultCopySuccessMessage = 'ID copied!'

const CopyItem = (props) => {
  const { copySuccessMessage = defaultCopySuccessMessage, value } = props

  const [showCopySuccess, setCopySuccess] = useState(false)


  function fallbackToCopy(text) {
    if (window.clipboardData && window.clipboardData.setData) {
      // IE specific code path to prevent textarea being shown while dialog is visible.
      return window.clipboardData.setData('Text', text)
    } else if (document.queryCommandSupported && document.queryCommandSupported('copy')) {
      const textarea = document.createElement('textarea')
      textarea.innerText = text
      // const parentElement=document.querySelector(".up-CopyItem-copy-button")
      const parentElement = document.getElementById('copy')
      if (!parentElement) {
        return
      }
      parentElement.appendChild(textarea)
      textarea.style.position = 'fixed' // Prevent scrolling to bottom of page in MS Edge.
      textarea.select()
      try {
        setCopySuccess(true)
        document.execCommand('copy') // Security exception may be thrown by some browsers.
      } catch (ex) {
        console.log('Copy to clipboard failed.', ex)
        return false
      } finally {
        parentElement.removeChild(textarea)
      }
    }
  }

  const copyID = () => {
    if (!navigator.clipboard) {
      fallbackToCopy(value)
      return
    }
    navigator.clipboard.writeText(value)
    setCopySuccess(true)
  }

  return showCopySuccess ? (
    <p>{copySuccessMessage}</p>
  ) : (
    <span id="copy">
      <button onClick={copyID}>Copy Item </button>
    </span>
  )
}

您可以在任何地方调用和重用该组件

const Sample=()=>(
   <CopyItem value="item-to-copy"/>
)

这是另一个用例,如果你想复制当前的url到你的剪贴板:

定义一个方法

const copyToClipboard = e => {
  navigator.clipboard.writeText(window.location.toString())
}

调用那个方法

<button copyToClipboard={shareLink}>
   Click to copy current url to clipboard
</button>

如果您希望以编程方式将数据写入剪贴板,可以在按钮上使用这个简单的内联onClick函数。

onClick={() => {navigator.clipboard.writeText(this.state.textToCopy)}}