在 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(); `);
到此这篇关于electron的webview和内嵌网页通信的方法的文章就介绍到这了,更多相关electron webview通信内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论