网页端和桌面端的electron通信Webview

1.electron使用Webview内镶嵌网页端

2.点击网页端触发electron的渲染进程

在网页端

javascript 复制代码
const sendDataToElectron = (data) => {
  console.log("🔥 [AiSystemEntrance] 准备发送数据到Electron:", data);

  // Electron webview 通信方法:使用特殊的 console 消息格式
  // 桌面端会监听 console-message 事件并解析这个特殊格式
  const message = `[ELECTRON_IPC]${JSON.stringify({
    type: "webview-message",
    data: data,
  })}[/ELECTRON_IPC]`;

  console.log(message); //使用console和桌面端通信

  // 也尝试其他方法作为备选--不过不生效,还是得是console通信
  try {
    // 尝试使用 postMessage (某些配置下可能工作)
    if (window.parent !== window) {
      window.parent.postMessage(
        {
          type: "webview-message",
          data: data,
        },
        "*"
      );
    }
  } catch (error) {
    console.error("❌ [AiSystemEntrance] postMessage 失败:", error);
  }

  console.log("📤 [AiSystemEntrance] 消息发送完成");
};

在electron端中的webview中使用handleWebViewReady

javascript 复制代码
 <webview
            key={tab.id}
            src={tab.url}
            className={`absolute inset-0 w-full h-[calc(100%-32px)] ${
              tab.active ? "visible" : "hidden"
            }`}
            webpreferences="nodeIntegration=true, contextIsolation=false"
            allowpopups="true"
            ref={(webview: WebViewElement | null) => {
              if (webview) {
                handleWebViewReady(webview);
              }
            }}
            onPageTitleUpdated={(e: WebViewTitleEvent) => {
              handleTitleUpdate(tab.id, e.title);
            }}
            onDidStartLoading={() => {
              console.log(`Started loading: ${tab.url}`);
            }}
            onDidFinishLoad={() => {
              console.log(`Finished loading: ${tab.url}`);
            }}
            onDidFailLoad={(e: WebViewLoadFailEvent) => handleLoadFail(e)}
          />

handleWebViewReady函数中使用原生 addEventListener 监听 console-message

javascript 复制代码
  const handleWebViewReady = useCallback(
    (webview: WebViewElement) => {
      webview.addEventListener("new-window", (e: NewWindowEvent) => {
        // console.log("New window requested:", e.url);
        addTab(e.url);
      });

      webview.addEventListener("will-navigate", (e: NavigationEvent) => {
        // console.log("Will navigate:", e.url);
      });

      webview.addEventListener("did-navigate", (e: NavigationEvent) => {
        // console.log("Did navigate:", e.url);
      });

      // 🔥 关键:使用原生 addEventListener 监听 console-message
      const handleConsoleMessage = (e: any) => {
        const message = e.message || "";
        
        // 检查是否是我们的特殊 IPC 消息格式
        if (
          message.includes("[ELECTRON_IPC]") &&
          message.includes("[/ELECTRON_IPC]")
        ) {
          try {
            // 提取 JSON 内容(处理 console.log 多参数格式:可能包含引号、空格等)
            const jsonStart =
              message.indexOf("[ELECTRON_IPC]") + "[ELECTRON_IPC]".length;
            const jsonEnd = message.indexOf("[/ELECTRON_IPC]");
            let jsonStr = message.substring(jsonStart, jsonEnd).trim();
            
            // 处理多种可能的格式:
            // 1. "[ELECTRON_IPC]" "{...}" "[/ELECTRON_IPC]"
            // 2. [ELECTRON_IPC] {...} [/ELECTRON_IPC]
            // 3. 移除首尾引号(单引号或双引号)
            jsonStr = jsonStr.replace(/^["']|["']$/g, "");
            // 移除可能的空格和换行
            jsonStr = jsonStr.trim();
            
            // console.log("🔍 [TabManager] 提取的 JSON 字符串:", jsonStr);
            
            const messageData = JSON.parse(jsonStr);

            // console.log("✅ [TabManager] 解析的 IPC 消息:", messageData);

            // 处理不同类型的消息
            if (messageData.type === "webview-message") {
              const data = messageData.data;

              // console.log("📦 [TabManager] 消息数据:", data);

              // 处理悬浮球点击事件
              if (data.type === "busEmitHandleFloatBallClick") {
          
                // 转发到主进程
                if (window.electron?.send) {
                // 渲染进程发送到主进程
                  window.electron.send("webview-open-legal-consultation", {
                    source: "webview",
                    action: "openLegalConsultation",
                    timestamp: Date.now(),
                  });
                } else {
                  console.error("❌ [TabManager] window.electron.send 不可用!");
                }
              } else {
                // 其他类型的消息也转发给主进程
                console.log("📤 [TabManager] 转发通用消息到主进程", data);
                window.electron?.send("webview-data", data);
              }
            }
          } catch (error) {
            console.error("❌ [TabManager] 解析 IPC 消息失败:", error);
            console.error("原始消息:", message);
          }
          return; // 已处理,直接返回
        }

        // 其他控制台消息正常输出
        console.log(`Webview console [${e.sourceId || 'unknown'}:${e.line || 'unknown'}]:`, message);
      };

      webview.addEventListener("console-message", handleConsoleMessage);
      console.log("✅ [TabManager] console-message 事件监听器已添加");
    },
    [addTab]
  );

重点,使用 React 的 onConsoleMessage 属性(可能不会触发)

javascript 复制代码
去掉代码:
onConsoleMessage={(e: WebViewConsoleEvent) =>
              handleConsoleMessage(e)
            }
使用原生 
webview.addEventListener("console-message", ...)
相关推荐
We་ct1 天前
LeetCode 5. 最长回文子串:DP + 中心扩展
前端·javascript·算法·leetcode·typescript
@yanyu6661 天前
登录注册功能-明文
vue.js·springboot
cn_mengbei1 天前
用React Native开发OpenHarmony应用:Reanimated共享元素过渡
javascript·react native·react.js
kyriewen1 天前
前端测试:别为了100%覆盖率而写测试,那是自欺欺人
前端·javascript·单元测试
Data_Journal1 天前
如何使用cURL更改User Agent
大数据·服务器·前端·javascript·数据库
掌心向暖RPA自动化1 天前
如何获取网页某个元素在屏幕可见部分的中心坐标影刀RPA懒加载坐标定位技巧
java·javascript·自动化·rpa·影刀rpa
竹林8181 天前
wagmi v2 多链钱包切换:一个 Uniswap 仿盘项目让我踩了三天坑
前端·javascript
你也向往长安城吗1 天前
最快的 JavaScript navmesh pathfinding3d 算法。
javascript
滕青山1 天前
在线PDF拆分工具核心JS实现
前端·javascript·vue.js
兔子零10241 天前
Ofox AI值得用吗?
前端·javascript·后端