electron的webview和内嵌网页如何通信

yezi__626 2024-06-14 11:03:04 阅读 88

在这里插入图片描述

在 Electron 的世界里,webview 标签相当于一个小盒子,里面可以装一个完整的网页,就像一个迷你浏览器。当你想和这个小盒子里的内容说话时(也就是进行通信),这里有几个方法可以帮你做到:

这里只写了两种方式,如果要是来找方案的客官。那直接看2就好。

1. 使用 preload 脚本

通过在 webview 标签中使用 preload 属性来指定一个脚本,该脚本在网页加载之前执行,但在网页的 JavaScript 环境中运行。这允许在不暴露全部 Node.js API 的情况下,向网页注入特定的 API 或者设置监听函数来实现双向通信。

<webview id="foo" src="http://example.com" preload="path/to/preload.js"></webview>

在 preload 脚本中,你可以使用 ipcRenderer 和 contextBridge 来安全地暴露功能:

const { contextBridge, ipcRenderer } = require('electron');contextBridge.exposeInMainWorld('electronAPI', { sendMessage: (message) => ipcRenderer.send('message-from-webview', message)});window.addEventListener('DOMContentLoaded', () => { // 从主进程接收消息 ipcRenderer.on('message-to-webview', (event, data) => { console.log(data); });});

【该方法目前遇到问题如下:】

webview内部页面加载报错:

在这里插入图片描述

2.postMessage

由于webview 标签创建了一个独立的渲染进程,它和主应用的渲染进程是隔离的。因此,webview 内部的页面拥有自己的全局 window 对象,你不能直接从外部的渲染进程访问 webview 内的 window 对象。

当你调用 webviewEl.executeJavaScript 方法时,你实际上是在 webview 内的上下文中执行 JavaScript 代码,因此可以通过注入脚本进行交互。

(1)electron的App.tsx模块发消息给webview内的页面:

const handleSendMessage = () => { if (webview.current) { const message = { type: 'messageFromElectron', text: '这里是electron发送的消息:electron->view' }; const script = `window.postMessage(${ JSON.stringify(message)}, '*')`; webview.current.executeJavaScript(script); } };

在webview内的页面接收:

mounted(){ const handleWebviewMessage = (event) => { const message = event.data; if (typeof message === 'object' && message !== null) { switch (message.type) { case 'messageFromElectron': console.info('Electron的消息', message); break; default: console.warn('接收到未知类型的消息', message); } } }; window.addEventListener('message',handleWebviewMessage); },

(2)webview内的页面发送消息给electron

sendMessageToElectron(){ window.postMessage({ type: 'messageFromView', text: 'Hello from Vue!' }, '*'); },

electron的App.tsx接收:

const handleWebviewMessage = (event) => { const message = event.data; if (typeof message === 'object' && message !== null) { switch (message.type) { case 'messageFromView': console.info('这里是webview的消息:webview->electron', message); break; default: console.warn('接收到未知类型的消息', message); } } }; useEffect(() => { const webviewEl = webview.current; const handleDomReady = () => { // 为 webview 内的 window 对象添加 message 事件监听器 webviewEl.executeJavaScript(` window.addEventListener('message', ${ handleWebviewMessage.toString()}) `); }; if (webviewEl) { webviewEl.addEventListener('dom-ready', handleDomReady); } // 清理工作 return () => { if (webviewEl) { // 移除之前添加的事件监听器,避免内存泄漏 webviewEl.removeEventListener('dom-ready', handleDomReady); } }; }, []);

知识科普:

executeJavaScript

executeJavaScript 方法的主要作用是在浏览器环境中异步执行 JavaScript 代码。这个方法是 Electron 中

webContents 对象提供的一个功能,允许开发者在 web 页面的上下文中运行任意的 JavaScript 代码字符串。

由于我使用的是react框架的ref来引用webview组件的,因此需要通过这个引用来获取 webview 的 webContents,进而使用 executeJavaScript 方法

使用场景:

● 与页面交互:你可以使用 executeJavaScript 来注入和执行自定义脚本,从而与网页中的 DOM 进行交互,修改网页内容,或者触发在网页中定义的 JavaScript 函数。

webview.executeJavaScript('document.getElementById("myButton").click()');

● 获取页面信息:通过执行返回值的 JavaScript 代码,你可以获取网页中的数据,比如页面标题、选定的文本或其他 DOM 元素的属性。

webview.executeJavaScript('document.title') .then(title => { console.log(`The page title is ${ title}`); });

● 网页自动化:可以用它来自动化测试网页的行为,例如自动填充表单、点击按钮等。

webview.executeJavaScript(` document.getElementById('username').value = 'exampleUser'; document.getElementById('password').value = 'examplePass'; document.getElementById('login-form').submit();`);



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。