网页端和桌面端的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", ...)
相关推荐
2501_9444241219 小时前
Flutter for OpenHarmony游戏集合App实战之连连看路径连线
android·开发语言·前端·javascript·flutter·游戏·php
利刃大大1 天前
【Vue】Vue2 和 Vue3 的区别
前端·javascript·vue.js
Lhuu(重开版1 天前
JS:正则表达式和作用域
开发语言·javascript·正则表达式
yuguo.im1 天前
我开源了一个 GrapesJS 插件
前端·javascript·开源·grapesjs
安且惜1 天前
带弹窗的页面--以表格形式展示
前端·javascript·vue.js
摘星编程1 天前
React Native鸿蒙:BiometricAuth指纹解锁实现
react native·react.js·harmonyos
摘星编程1 天前
用React Native开发OpenHarmony应用:NFC读取标签数据
javascript·react native·react.js
哈哈你是真的厉害1 天前
小白基础入门 React Native 鸿蒙跨平台开发:实现一个简单的文件路径处理工具
react native·react.js·harmonyos
AGMTI1 天前
webSock动态注册消息回调函数功能实现
开发语言·前端·javascript
码界奇点1 天前
基于SpringBoot+Vue的前后端分离外卖点单系统设计与实现
vue.js·spring boot·后端·spring·毕业设计·源代码管理