异步剪贴板API“ClipboardItem未定义” - Reactjs将图像复制到剪贴板

问题描述 投票:0回答:4

我正在研究 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。

reactjs image npm clipboard webapi
4个回答
6
投票

不幸的是,截至本回答时,Firefox 不支持

ClipboardItem
。 (可以通过
about:config
设置启用支持;但当然,大多数互联网用户不会这样做。)

来源:https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem#browser_compatibility


2
投票

要寻找的东西:

  1. 浏览器支持剪贴板
  2. HTTPS 或本地主机上的安全源。 请参阅这篇文章。
  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>
);

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


1
投票

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

window.ClipboardItem(...)

0
投票

我相信我可能已经找到了解决方案。

如果您在启动 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>
);
© www.soinside.com 2019 - 2024. All rights reserved.