在Electron中处理表单的正确方法是什么?



表单 html 和提交事件是"渲染器"的一部分。 提交的数据应在主流程中可用。 提交表单并使该数据在 main.js 中可访问的正确方法是什么?

我应该简单地使用"远程"模块将数据从main传递给函数.js还是有更好的方法?

我们使用服务(Angular)来处理窗口中的表单数据。然后通知remote,如果需要。


从您的renderer中,您可以将数据发送到ipc,然后在您的main.js中捕获此事件和传递的表单数据:

// renderer.js
let ipcRenderer = require('electron').ipcRenderer;
ipcRenderer.send('submitForm', formData);
// main.js
ipcMain.on('submitForm', function(event, data) {
// Access form data here
});

您还可以将消息从main.js发送回renderer

任一同步

// main.js
ipcMain.on('submitForm', function(event, data) {
// Access form data here
event.returnValue = {"any": "value"};
});

异步

// main.js
ipcMain.on('submitForm', function(event, data) {
// Access form data here
event.sender.send('formSubmissionResults', results);
});
// renderer.js
ipcRenderer.on('formSubmissionResults', function(event, args) {
let results = args.body;
});

关于如何做到这一点有几种变体,但都是通过IPC进行的。

IPC(进程间通信)是将数据从渲染进程获取到主进程的唯一方法,并且是事件驱动的。其工作方式是,您可以使用自定义事件,进程侦听这些事件并在事件发生时返回一些内容。

@Adam Eri 陈述的示例是文档中 ipcMain 示例的变体,但此方法并非一刀切。

这么说的原因是,如果你试图通过菜单(通常在主进程上运行)或通过 Vue 或 Angular 等前端框架的组件发送事件,问题很快就会变得复杂。

我举几个例子:

将远程与 Web 内容结合使用

就你的观点而言,是的,您可以使用电子遥控器,但出于形式目的,这不是推荐的方法。根据文档,远程的重点是

使用渲染器进程中的主流程模块

tl:dr -由于其同步性质,此过程可能会导致死锁,可能导致事件对象泄漏(由于垃圾回收),并导致回调的意外结果。

可以从文档中得到进一步的解释,但最终这是设置为在渲染过程中使用dialogmenu等项。

索引.js(主进程)

const { app, BrowserWindow, ipcMain } = require('electron');
const path = require ('path');
const fs = require('fs');
const os = require('os');
let window;
function createWindow(){
window = new BrowserWindow({
show: false
});
window.loadURL(`file://${__dirname}/index.html`);
window.once('ready-to-show', function (){
window.show();
});
window.webContents.openDevTools();
let contents = window.webContents;
window.on('closed', function() {
window = null;
});
}
exports.handleForm = function handleForm(targetWindow, firstname) {
console.log("this is the firstname from the form ->", firstname)
targetWindow.webContents.send('form-received', "we got it");
};
app.on('ready', function(){
createWindow();
});

索引.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Electron App</title>
</head>
<body>
<form action="#" id="ipcForm2">
First name:<br>
<input type="text" name="firstname" id="firstname" value="John">
<br>
Last name:<br>
<input type="text" name="lastname" id="lastname" value="Smith">
<br><br>
<input id="submit" type="submit" value="submit">
</form>
<p id="response"></p>
<script src='renderFile.js'></script>
</body>
</html>

渲染文件.js(渲染进程)

const { remote, ipcRenderer } = require('electron');
const { handleForm} = remote.require('./index');
const currentWindow = remote.getCurrentWindow();
const submitFormButton = document.querySelector("#ipcForm2");
const responseParagraph = document.getElementById('response')
submitFormButton.addEventListener("submit", function(event){
event.preventDefault();   // stop the form from submitting
let firstname = document.getElementById("firstname").value;
handleForm(currentWindow, firstname)
});
ipcRenderer.on('form-received', function(event, args){
responseParagraph.innerHTML = args
/*
you could choose to submit the form here after the main process completes
and use this as a processing step
*/
});

传统工控机

索引.js(主进程)

const { app, BrowserWindow, ipcMain } = require('electron');
const path = require ('path');
const fs = require('fs');
const os = require('os');
let window;
function createWindow(){
window = new BrowserWindow({
show: false
});
window.loadURL(`file://${__dirname}/index.html`);
window.once('ready-to-show', function (){
window.show();
});
window.webContents.openDevTools();
let contents = window.webContents;
window.on('closed', function() {
window = null;
});
}
ipcMain.on('form-submission', function (event, firstname) {
console.log("this is the firstname from the form ->", firstname)
});
app.on('ready', function(){
createWindow();
});

索引.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Electron App</title>
</head>
<body>
<form name="ipcForm" onSubmit="JavaScript:sendForm(event)">
First name:<br>
<input type="text" name="firstname" id="firstname" value="John">
<br>
Last name:<br>
<input type="text" name="lastname" id="lastname" value="Smith">
<br><br>
<input type="submit" value="Submit">
</form>
<script src='renderFile.js'></script>
</body>
</html>

渲染文件.js(渲染进程)

const ipcRenderer = require('electron').ipcRenderer;
function sendForm(event) {
event.preventDefault() // stop the form from submitting
let firstname = document.getElementById("firstname").value;
ipcRenderer.send('form-submission', firstname)
}

使用网页内容

第三个可能的选择是webContent.executeJavascript,用于从主进程访问渲染器进程。此说明来自远程文档部分。

总结

如您所见,关于如何使用Electron处理表单,有一些选项。只要你使用IPC,你应该没问题;只是你如何使用它会给你带来麻烦。我已经展示了用于处理表单的纯JavaScript选项,但是有无数种方法可以做到这一点。当你将前端框架带入组合时,它会变得更加有趣。

我个人尽可能使用传统的IPC方法。

希望能为您解决问题!

我不一定推荐这种方式,因为它可能会干扰其他功能,但这是一种更简洁的方法

const str = `
<form action="form://submit" >
<input name="test" >
<button type="submit"> OK </button>
</form>
`
promptWindow.loadURL(`data:text/html;base64,${Buffer.from(str).toString("base64")}`)
promptWindow.webContents.session.protocol.registerStringProtocol("form", e => {
const request = new URL(e.url)
const data = request.searchParams // {test:"inputvalue"}
debugger;
})

远程是共享数据的好方法。使用全局变量并与我们的电子应用程序的其他页面共享它们。因此,基于以下IPC方法,我能够以这种方式管理它:

1) 将此代码添加到主.js文件中:

global.MyGlobalObject = {
variable_1: '12345'
}

2)在您的第一页上使用它来更新全局变量值:

require('electron').remote.getGlobal('MyGlobalObject').variable_1= '4567'

3)最后,在第二页上使用类似的东西,您将在其中访问修改后的全局变量并打印它:

console.log(require('electron').remote.getGlobal('MyGlobalObject').variable_1)

你可以在electron的文档中找到同样的东西。

相关内容

最新更新