我使用的是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()
}
受@nate回答的启发,我创建了一个withCopyText反应钩子。并且,添加了navigator.clipboard.writeText支持execCommand回退。
钩子意味着它可以跨许多组件重用,而无需重复代码。有关实现,请参阅示例组件CopyText。
import React, { useRef, useState } from 'react';
const withCopyText = (textElementRef) => {
if (!textElementRef) throw 'withCopyText: ref is required';
const [copyStatus, setCopyStatus] = useState('');
const [support, setSupport] = useState({
navigatorClipboard: !!navigator.clipboard,
exec: !!document.queryCommandSupported('copy'),
});
const copyToClipboard = (e) => {
if ('' !== copyStatus) {
setCopyStatus('');
await new Promise((resolve) => setTimeout(resolve, 200));
}
// clipboard.writeText has wide but not 100% support
// https://caniuse.com/?search=writeText
if (support.navigatorClipboard) {
try {
navigator.clipboard.writeText(textElementRef.current.value);
return setCopyStatus('success');
} catch (e) {
setSupport({ ...support, navigatorClipboard: false });
}
}
// execCommand has > 97% support but is deprecated, use it as a fallback
// https://caniuse.com/?search=execCommand
// https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand
if (!support.navigatorClipboard) {
try {
textElementRef.current.select();
document.execCommand('copy');
e.target.focus();
setCopyStatus('success');
} catch (e) {
setSupport({ ...support, exec: false });
return setCopyStatus('fail');
}
}
};
return {
copyStatus,
copyToClipboard,
support: Object.values(support).includes(true),
};
};
const CopyText = ({ text }) => {
const textElementRef = useRef(null);
const { copyStatus, copyToClipboard, support } = withCopyText(textElementRef);
return (
<span>
{support && <button onClick={copyToClipboard}>Copy</button>}
{'success' === copyStatus && <span>Copied to clipboard!</span>}
{'fail' === copyStatus && <span>Sorry, copy to clipboard failed</span>}
<input type="text" ref={textElementRef} value={text} readOnly={true} />
</span>
);
};
export { CopyText, withCopyText };
找到了最好的方法。我是说最快的方法:w3school
https://www.w3schools.com/howto/howto_js_copy_clipboard.asp
在react函数组件中。创建名为handleCopy的函数:
function handleCopy() {
// get the input Element ID. Save the reference into copyText
var copyText = document.getElementById("mail")
// select() will select all data from this input field filled
copyText.select()
copyText.setSelectionRange(0, 99999)
// execCommand() works just fine except IE 8. as w3schools mention
document.execCommand("copy")
// alert the copied value from text input
alert(`Email copied: ${copyText.value} `)
}
<>
<input
readOnly
type="text"
value="exemple@email.com"
id="mail"
/>
<button onClick={handleCopy}>Copy email</button>
</>
如果不使用React, w3schools也有一个很酷的方法来做到这一点,工具提示包括:https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_copy_clipboard2
如果使用React,一个很酷的想法是:使用Toastify提醒消息。
https://github.com/fkhadra/react-toastify这是一个很容易使用的库。
安装后,你可以更改这一行:
alert(`Email copied: ${copyText.value} `)
比如:
toast.success(`Email Copied: ${copyText.value} `)
如果你想使用它,不要忘记安装toastify。导入ToastContainer,同时也导入css:
import { ToastContainer, toast } from "react-toastify"
import "react-toastify/dist/ReactToastify.css"
并将烤面包的容器放入里面返回。
import React from "react"
import { ToastContainer, toast } from "react-toastify"
import "react-toastify/dist/ReactToastify.css"
export default function Exemple() {
function handleCopy() {
var copyText = document.getElementById("mail")
copyText.select()
copyText.setSelectionRange(0, 99999)
document.execCommand("copy")
toast.success(`Hi! Now you can: ctrl+v: ${copyText.value} `)
}
return (
<>
<ToastContainer />
<Container>
<span>E-mail</span>
<input
readOnly
type="text"
value="myemail@exemple.com"
id="mail"
/>
<button onClick={handleCopy}>Copy Email</button>
</Container>
</>
)
}