异步剪贴板API "ClipboardItem is not defined" - Reactjs将图像复制到剪贴板

6

我正在研究React js,我使用npm创建了我的应用程序,并使用create-react-app进行了构建。我试图构建一个按钮,以将图像复制到剪贴板中。幸运的是,我找到了这个 npm库,似乎可以正常工作!但是,我一直在考虑为什么我不能使用内置的异步剪贴板API来复制该图像(文本复制功能正常)。我在这里读了一篇非常启发性的指南(链接),并继续阅读其他很棒的指南(链接),所以我尝试了所有建议的代码,在那里和其他页面(尽管它们似乎并不真正改变功能,但我还是得尝试)。每次尝试都出现相同的错误,无法编译:“'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)配置引起的 - 类似问题。可以使用类似此库的内容,创建画布并从中复制图像。 解决方案或使其正常工作的方法: 在使用ClipboardItem之前,按照以下方式进行调用:
const { ClipboardItem } = window;

注意:这也适用于其他构造函数,例如toBlob和HTMLCanvasElement,它们具有相同的问题。

3个回答

6

有什么解决方法? - Fazwelington
1
@volley,我使用https://clipboardjs.com/取得了成功。(无关联,我只是一个粉丝!)它正在我的网站https://clipemoji.com/上使用,如果你想看一个实时的例子。 - Jon Schneider
1
@volley,如果您不想在项目中包含整个(虽然很小)的外部脚本文件,我也成功地使用了这个答案中提出的方法:https://dev59.com/-loV5IYBdhLWcg3wIb74#48020189 - Jon Schneider

2

只需在ClipboardItem之前添加窗口,如下所示:

window.ClipboardItem(...)

2
要注意的事项:
  1. 浏览器支持剪贴板
  2. 安全来源于HTTPS或localhost。请参阅此帖子。
  3. 函数的调用方式-在OP的情况下-onClick和异步。

问题在于默认情况下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>
);

最后,您可以返回一个 链式promise

1
我需要看看你是如何设置和调用复制函数的。你能否更新你的帖子,展示整个组件,只包含复制和粘贴函数以及你返回给浏览器的JSX代码。 - Sean W
1
放心吧,伙计。我刚刚创建了一个测试组件,可以很好地与 copy-img-clipboard 库一起使用。我推迟回答是因为我还测试了一下如何使我的本地主机更安全,但遗憾的是仍然失败了。 - Andres S
1
现在试试吧,我将你的代码复制粘贴到我的注释中,我只是将它放在我的TypeScript中,你有"clipoboard",应该是"clipboard"——注意多了一个"o"。我刚刚在Chrome和本地主机上运行了上面的完全相同的代码,对我有效。 - Sean W
1
使用“npx create-react-app”创建React应用?可能是我的基本配置出了问题,我不知道是什么原因。 - Andres S
1
嘿,老兄!我成功了!我调用了:“const { ClipboardItem } = window;”,它适用于toBlob、HTMLCanvasElement、Blob、atob等。我仍然认为问题在于npm的CRA配置,但这种方法可行! - Andres S
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接