在reactJS中,如何将文本复制到剪贴板?

Duk*_*gal 105 javascript clipboard reactjs

我正在使用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()
}
Run Code Online (Sandbox Code Playgroud)

Nat*_*ate 128

我个人认为不需要图书馆.看看http://caniuse.com/#feat=clipboard它现在得到了广泛的支持,但你仍然可以做一些事情,比如查看当前客户端中是否存在该功能,如果不存在则只需隐藏复制按钮.

import React from 'react';

class CopyExample extends React.Component {

  constructor(props) {
    super(props);

    this.state = { copySuccess: '' }
  }

  copyToClipboard = (e) => {
    this.textArea.select();
    document.execCommand('copy');
    // This is just personal preference.
    // I prefer to not show the the whole text area selected.
    e.target.focus();
    this.setState({ copySuccess: 'Copied!' });
  };

  render() {
    return (
      <div>
        {
         /* Logical shortcut for only displaying the 
            button if the copy command exists */
         document.queryCommandSupported('copy') &&
          <div>
            <button onClick={this.copyToClipboard}>Copy</button> 
            {this.state.copySuccess}
          </div>
        }
        <form>
          <textarea
            ref={(textarea) => this.textArea = textarea}
            value='Some text to copy'
          />
        </form>
      </div>
    );
  }

}

export default CopyExample;
Run Code Online (Sandbox Code Playgroud)

更新:使用React 16.7.0-alpha.0中的React Hook重写

import React, { useRef, useState } from 'react';

export default function CopyExample() {

  const [copySuccess, setCopySuccess] = useState('');
  const textAreaRef = useRef(null);

  function copyToClipboard(e) {
    textAreaRef.current.select();
    document.execCommand('copy');
    // This is just personal preference.
    // I prefer to not show the the whole text area selected.
    e.target.focus();
    setCopySuccess('Copied!');
  };

  return (
    <div>
      {
       /* Logical shortcut for only displaying the 
          button if the copy command exists */
       document.queryCommandSupported('copy') &&
        <div>
          <button onClick={copyToClipboard}>Copy</button> 
          {copySuccess}
        </div>
      }
      <form>
        <textarea
          ref={textAreaRef}
          value='Some text to copy'
        />
      </form>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

  • 这是最好的答案.我们不应该鼓励开发人员为每件小事使用包,除非他们需要旧的浏览器支持. (15认同)
  • 这现在已经过时 https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand (8认同)
  • 我收到 TypeError: textAreaRef.current.select is not a function (4认同)
  • 仅作记录:唯一的问题是,如果您要复制页面上某些文本元素中尚未包含的文本,则需要破解一组DOM元素,设置文本,进行复制,清理一下 对于很小的东西,这是很多代码。通常,我会同意不鼓励开发人员不断安装库。 (2认同)
  • 对于此特定问题,文本已在页面上的元素中。在什么情况下要复制的页面上没有元素的可见文本会出现在什么情况下?这是一个完全不同的问题,我很乐意为您提供解决方案。您不需要用react破解任何东西,您只需在render函数中提供一个隐藏元素即可保存文本。无需临时创建元素。 (2认同)
  • 我收到此打字稿错误:“从不”类型上不存在“属性“选择” (2认同)
  • 如果您得到的 textAreaRef.current.select 不是一个函数,请确保您的引用实际上位于 &lt;textarea&gt; HTML 标记上。我在这里找到了对我有用的答案:/sf/ask/2536204891/ (2认同)

jer*_*naa 73

您无需外部库即可完成此操作,例如:在按钮内

<button 
  onClick={() =>  navigator.clipboard.writeText('Copy this text to clipboard')}
>
  Copy
</button>
Run Code Online (Sandbox Code Playgroud)

对于 Internet Explorer 11 和更旧的浏览器,您可能需要稍微更改代码,这是一个示例:

<button 
  onClick={() =>  window.clipboardData.setData("Text", 'Copy this text to clipboard')}>
 Copy
</button>
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。

  • 我收到以下错误:``TypeError:无法读取未定义的属性'setData'`` (2认同)

Gar*_*ubb 58

如果要以编程方式将数据写入剪贴板,请在按钮上使用此简单的内联onClick函数.

onClick={() => {navigator.clipboard.writeText(this.state.textToCopy)}}
Run Code Online (Sandbox Code Playgroud)

  • 由于我陷入了这个困境(在 Chrome 上),只有当您的页面是从安全源(HTTPS 或 localhost)加载时,`navigator.clipboard` 才会起作用。如果需要,您可以检查 [window.isSecureContext](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts)。 (11认同)
  • navigator.clipboard 不支持所有浏览器 (9认同)
  • 似乎它在2018年的主流浏览器上得到了很好的支持https://caniuse.com/#search=clipboard (6认同)
  • 根据您提供的链接,它似乎完全支持safari ... (2认同)
  • 最适合我的用例,该用例中的文本实际上不在页面上。谢谢 (2认同)
  • 到了 2021 年,这应该是公认的答案。对“navigator.clipboard”的支持已经足够普遍了。 (2认同)
  • 虽然这确实很有用,但它仅适用于作为本地主机或使用 https 的站点进行开发。 (2认同)

Dre*_*ter 38

你应该考虑使用像@Shubham这样的软件包来建议,但我根据你描述的内容创建了一个有效的代码:http://codepen.io/dtschust/pen/WGwdVN?edit = 1111 .它可以在我的浏览器中使用chrome,或许你可以看到我在那里做了一些你错过的东西,或者你的应用程序中是否有一些扩展的复杂性阻止了它的工作.

// html
<html>
  <body>
    <div id="container">

    </div>
  </body>
</html>


// js
const Hello = React.createClass({
  copyToClipboard: () => {
    var textField = document.createElement('textarea')
    textField.innerText = 'foo bar baz'
    document.body.appendChild(textField)
    textField.select()
    document.execCommand('copy')
    textField.remove()
  },
  render: function () {
    return (
      <h1 onClick={this.copyToClipboard}>Click to copy some text</h1>
    )
  }
})

ReactDOM.render(
<Hello/>,
  document.getElementById('container'))
Run Code Online (Sandbox Code Playgroud)

  • 可能更好的跨浏览器支持,以及在需要修复错误的情况下更多关注包 (6认同)
  • 为什么包装比您的解决方案更好? (3认同)

Gas*_*ass 35

2021年剪贴板将得到主流浏览器的良好支持。一种方法是首先构建复制到剪贴板函数,然后使用onClick事件处理程序调用它。

function copy(text){
  navigator.clipboard.writeText(text)
}
Run Code Online (Sandbox Code Playgroud)

为了防止硬编码,我们假设 被string分配给一个名为someText

<span onClick={() => copy(someText)}>
  {someText}
</span>
Run Code Online (Sandbox Code Playgroud)


Shu*_*tri 30

最简单的方法是使用react-copy-to-clipboardnpm包.

您可以使用以下命令安装它

npm install --save react react-copy-to-clipboard
Run Code Online (Sandbox Code Playgroud)

以下列方式使用它.

const App = React.createClass({
  getInitialState() {
    return {value: '', copied: false};
  },


  onChange({target: {value}}) {
    this.setState({value, copied: false});
  },


  onCopy() {
    this.setState({copied: true});
  },


  render() {
    return (
      <div>

          <input value={this.state.value} size={10} onChange={this.onChange} />

        <CopyToClipboard text={this.state.value} onCopy={this.onCopy}>
          <button>Copy</button>
        </CopyToClipboard>

                <div>
        {this.state.copied ? <span >Copied.</span> : null}
                </div>
        <br />

        <input type="text" />

      </div>
    );
  }
});

ReactDOM.render(<App />, document.getElementById('container'));
Run Code Online (Sandbox Code Playgroud)

以下链接提供了详细说明

https://www.npmjs.com/package/react-copy-to-clipboard

这是一个奔跑的小提琴.


小智 27

带有反应钩子的最佳解决方案,不需要外部库

import React, { useState } from 'react';

const MyComponent = () => {
const [copySuccess, setCopySuccess] = useState('');

// your function to copy here

  const copyToClipBoard = async copyMe => {
    try {
      await navigator.clipboard.writeText(copyMe);
      setCopySuccess('Copied!');
    } catch (err) {
      setCopySuccess('Failed to copy!');
    }
  };

return (
 <div>
    <Button onClick={() => copyToClipBoard('some text to copy')}>
     Click here to copy
     </Button>
  // after copying see the message here
  {copySuccess}
 </div>
)
}
Run Code Online (Sandbox Code Playgroud)

在此处查看有关 navigator.clip board 的更多文档,navigator.clipboard 文档 navigotor.clipboard 受到大量浏览器的支持,请查看此处支持的浏览器


Dam*_*zki 15

为什么不使用事件clipboardData集合方法e.clipboardData.setData(type, content)

在我看来是实现在剪贴板中推送smth的最直接的方法,检查一下(我用它来修改数据,而本机复制操作):

...

handleCopy = (e) => {
    e.preventDefault();
    e.clipboardData.setData('text/plain', 'Hello, world!');
}

render = () =>
    <Component
        onCopy={this.handleCopy}
    />
Run Code Online (Sandbox Code Playgroud)

我遵循了这条道路:https://developer.mozilla.org/en-US/docs/Web/Events/copy

干杯!

编辑:为了测试目的,我添加了codepen:https://codepen.io/dprzygodzki/pen/ZaJMKb

  • @KarlPokus提问者只是在寻找Chrome解决方案 (3认同)
  • @OliverDixon 它是 React 事件的默认对象。https://reactjs.org/docs/events.html (2认同)

Job*_*uba 9

无需安装第三方软件包。我尽量保持简单。这对我来说效果很好。

import React, { useState } from "react"    
function MyApp() {
    const [copySuccess, setCopySuccess] = useState(null);
    const copyToClipBoard = async copyMe => {
       try {
           await navigator.clipboard.writeText(copyMe);
           setCopySuccess('Copied!');
       } 
       catch (err) {
           setCopySuccess('Failed to copy!');
       }
    };
     
    return (
        <button onClick={(e) => copyToClipBoard(what you want to copy goes here)} >
           My button
        </button>    
       )
    }
Run Code Online (Sandbox Code Playgroud)


Kup*_*upi 8

你的代码应该完美运行,我以同样的方式使用它.只有确保如果在弹出屏幕内触发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);
}
Run Code Online (Sandbox Code Playgroud)


Fla*_*che 8

使用 Material 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;
Run Code Online (Sandbox Code Playgroud)

该按钮如下所示:

在此输入图像描述

当你点击它时:

在此输入图像描述

来源:https ://fwuensche.medium.com/react-button-to-copy-to-clipboard-75ef5ecdc708


小智 7

我认为上述方法与上面的方法非常相似,但是我认为它更加具体。在这里,父组件将通过url(或您想要的任何文本)作为道具。

import * as React from 'react'

export const CopyButton = ({ url }: any) => {
  const copyToClipboard = () => {
    const textField = document.createElement('textarea');
    textField.innerText = url;
    document.body.appendChild(textField);
    textField.select();
    document.execCommand('copy');
    textField.remove();
  };

  return (
    <button onClick={copyToClipboard}>
      Copy
    </button>
  );
};
Run Code Online (Sandbox Code Playgroud)


Sky*_*Sky 7

首先创建 BTN,然后添加此 onClick:

onClick={() =>  navigator.clipboard.writeText(textState)}
Run Code Online (Sandbox Code Playgroud)

或者

onClick={() =>  navigator.clipboard.writeText('Your text for copy')}
Run Code Online (Sandbox Code Playgroud)


jas*_*ard 6

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

定义方法

const copyToClipboard = e => {
  navigator.clipboard.writeText(window.location.toString())
}
Run Code Online (Sandbox Code Playgroud)

调用那个方法

<button copyToClipboard={shareLink}>
   Click to copy current url to clipboard
</button>
Run Code Online (Sandbox Code Playgroud)


小智 6

简单的答案是

navigator.clipboard.writeText(“值”)


Ant*_*újo 5

这对我有用:

const handleCopyLink = useCallback(() => {
    const textField = document.createElement('textarea')
    textField.innerText = url
    document.body.appendChild(textField)
    if (window.navigator.platform === 'iPhone') {
      textField.setSelectionRange(0, 99999)
    } else {
      textField.select()
    }
    document.execCommand('copy')
    textField.remove()
    
    toast.success('Link successfully copied')
  }, [url])
Run Code Online (Sandbox Code Playgroud)