我正在研究 React js,我使用 npm 通过 create-react-app 创建了我的应用程序。我试图构建一个按钮来获取图像并将其写入剪贴板。幸运的是,我发现 this npm 库似乎工作得很好!但我一直在想为什么我不能使用 ¿内置? 异步剪贴板 API 来复制图像(文本复制工作正常)。我读了一本非常有启发性的指南here,并继续阅读其他很棒的指南here,所以我尝试了那里和其他页面中建议的所有代码(尽管它们似乎并没有真正改变功能,但我必须尝试)。我在每次尝试时都遇到了同样的错误,阻碍了编译:“'ClipboardItem'未定义no-undef”。例如,一个代码是这样的:
const response = await fetch('valid img url of a png image');
const blob = await response.blob();
await navigator.clipboard.write([new ClipboardItem({ 'image/png': blob})]);
看起来很简单,很容易理解。问题是,当您需要将数据放入剪贴板可以读取的表单中,使其成为一个 blob 时,因为我需要 ClipboardItem 构造函数,而我的应用程序似乎无法识别它。当然,不断返回 ClipboardItem 未定义,或者如果我以某种方式定义它,则表示它不是构造函数。我尝试使用其他构造函数,例如 Blob(),但遇到了同样的问题。最后一件事让我一直在思考,由于我是编程世界的新手,如果有一些基本的东西我不知道 Web API 与 Node 或 Reactjs 的交互,如果有解决方案,当然!提前谢谢你们,你们太棒了!
编辑:根据要求添加整个组件代码:
import React from "react";
function TestingClipAPI () {
async function handleScreenshot () {
const response = await fetch('https://i.postimg.cc/d0hR8HfP/telefono.png');
const blob = await response.blob();
await navigator.clipboard.write([new ClipboardItem({ 'image/png': blob})]);
};
return (
<div>
<button onClick={handleScreenshot} id="buttonID">test</button>
</div>
)
};
export default TestingClipAPI;
可能的问题:这可能是由于 CRA(Create-React-App)配置 - 类似问题。可以完成类似库linked之类的操作,创建画布并从那里复制图像。
解决方案或使其正常工作的方法:在使用 ClipboardItem 之前以这种方式进行调用:
const { ClipboardItem } = window;
注意: 这也适用于其他具有相同问题的构造函数,例如 toBlob 和 HTMLCanvasElement。
不幸的是,截至本回答时,Firefox 不支持
ClipboardItem
。 (可以通过 about:config
设置启用支持;但当然,大多数互联网用户不会这样做。)
来源:https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem#browser_compatibility
要寻找的东西:
问题是 onClick 默认情况下不是异步的,您没有等待响应,而且 navigator.clipboard 中也有拼写错误。
const handleScreenshot = async () => {
try {
const response = await fetch(
"https://i.postimg.cc/d0hR8HfP/telefono.png"
);
const blob = await response.blob();
await navigator.clipboard.write([
new ClipboardItem({ "image/png": blob }),
]);
} catch (err) {
console.error(err);
}
}
return (
<button onClick={async () => await handleScreenshot()} id="buttonID">
test
</button>
);
内联函数之间存在权衡,下面是替代方案。我个人会使用后一种方法。
function handleScreenshot() {
async function screenShot() {
try {
const response = await fetch(
"https://i.postimg.cc/d0hR8HfP/telefono.png"
);
const blob = await response.blob();
await navigator.clipboard.write([
new ClipboardItem({ "image/png": blob }),
]);
} catch (err) {
console.error(err);
}
}
screenShot();
}
return (
<button onClick={handleScreenshot} id="buttonID">
test
</button>
);
最后,您可以返回一个链式承诺。
只需在 ClipboardItem 前面添加窗口,如下所示
window.ClipboardItem(...)
我相信我可能已经找到了解决方案。
如果您在启动 React App 时看到浏览器中弹出以下错误:
这是解决方案。在使用
ClipboardItem
之前添加此行:
// eslint-disable-next-line no-undef
扩展@Sean W 的答案:
function handleScreenshot() {
async function screenShot() {
try {
const response = await fetch(
"https://i.postimg.cc/d0hR8HfP/telefono.png"
);
const blob = await response.blob();
// eslint-disable-next-line no-undef
const clipItem = new ClipboardItem({ "image/png": blob });
await navigator.clipboard.write([clipItem]);
} catch (err) {
console.error(err);
}
}
screenShot();
}
return (
<button onClick={handleScreenshot} id="buttonID">
test
</button>
);