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

问题描述:

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

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

+0

你是从前端框架的角度来问,还是纯粹的电子? –

我们使用服务(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 
}); 

您也可以发送邮件回renderer来自main.js

要么同步

// 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 example上的一个变体,但此方法并非一刀切。

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

我举几个例子:

WebContents

要贵点的远程使用,是的,你可以使用电子remote,但形式的目的,是不推荐的方法 。基于文档,远程的点是

从渲染过程

TL使用主处理模块:博士 - 此过程可能导致死锁,由于其同步性质,可引起事件对象泄漏(由于垃圾收集),并导致回调意想不到的结果。

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

index.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(); 
}); 

的index.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> 

renderFile.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 
    */ 
}); 

传统IPC

index.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(); 
}); 

的index.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> 

renderFile.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) 
} 

使用WebContents

一种可能的第三个选项是webContents.executeJavascript从主进程访问渲染器进程。来自remote文档部分的此解释。

摘要

正如你所看到的,有关于如何使用电子表格处理几个选项。只要你使用IPC,你应该没问题;它只是你如何使用它,可以让你陷入困境。我已经展示了用于处理表单的纯javascript选项,但是有无数的方法可以做到这一点。当你将一个前端框架融合到一起时,它变得更加有趣。

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

希望能为您解决问题!

+1

我还不清楚为什么不推荐传统的IPC方式。如果我不使用角度等任何框架怎么办? – JerryGoyal

+0

如果你阅读了上面的总结,那么你会更清楚。我不推荐传统IPC以外的任何东西(你必须将这个答案与Adam的上面的我的混淆)。我举例说明如何在没有框架的情况下做到这一点 –