网页端和桌面端的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", ...)
相关推荐
EchoEcho7 小时前
深入理解 Vue.js 渲染机制:从声明式到虚拟 DOM 的完整实现
vue.js
早點睡3907 小时前
高级进阶 ReactNative for Harmony 项目鸿蒙化三方库集成实战:react-native-drag-sort
react native·react.js·harmonyos
C澒8 小时前
Vue 项目渐进式迁移 React:组件库接入与跨框架协同技术方案
前端·vue.js·react.js·架构·系统架构
xiaoxue..8 小时前
合并两个升序链表 与 合并k个升序链表
java·javascript·数据结构·链表·面试
要加油哦~8 小时前
AI | 实践教程 - ScreenCoder | 多agents前端代码生成
前端·javascript·人工智能
一个public的class8 小时前
你在浏览器输入一个网址,到底发生了什么?
java·开发语言·javascript
青茶3608 小时前
php怎么实现订单接口状态轮询请求
前端·javascript·php
火车叼位9 小时前
脚本伪装:让 Python 与 Node.js 像原生 Shell 命令一样运行
运维·javascript·python
VT.馒头9 小时前
【力扣】2727. 判断对象是否为空
javascript·数据结构·算法·leetcode·职场和发展
发现一只大呆瓜9 小时前
虚拟列表:从定高到动态高度的 Vue 3 & React 满分实现
前端·vue.js·react.js