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

Elf*_*lfy 24 javascript forms node.js electron

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

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

Ada*_*Eri 11

我们使用服务(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
});
Run Code Online (Sandbox Code Playgroud)

您也可以发送邮件回renderermain.js.

无论是同步:

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

异步:

// 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;
});
Run Code Online (Sandbox Code Playgroud)


uns*_*age 7

关于如何做到这一点有几种变化,但都是通过IPC

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

@Adam Eri所述的示例是文档中的ipcMain示例的变体,但这种方法并非一刀切.

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

我举几个例子:

使用Remote与WebContents

对于您的观点,是的,您可以使用电子遥控器,但出于表格的目的,它不是推荐的方法.根据文档,远程的要点是 

使用渲染器过程中的主要过程模块

tl:dr-这个进程由于其同步性质可能导致死锁,可能导致事件对象泄漏(由于垃圾收集),并导致回调意外结果.

进一步的解释可以从文档可以了,但最终它被设置为使用类的物品dialog,并menu在渲染过程.

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();
});
Run Code Online (Sandbox Code Playgroud)

的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>
Run Code Online (Sandbox Code Playgroud)

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
    */
});
Run Code Online (Sandbox Code Playgroud)

传统的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();
});
Run Code Online (Sandbox Code Playgroud)

的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>
Run Code Online (Sandbox Code Playgroud)

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)
}
Run Code Online (Sandbox Code Playgroud)

使用WebContents

可能的第三个选项是webContents.executeJavascript,用于从主进程访问渲染器进程.远程文档部分的解释.

摘要

如您所见,有一些关于如何使用Electron处理表单的选项.只要你使用IPC,你应该没事; 它只是你如何使用它可以让你陷入困境.我已经展示了处理表单的简单javascript选项,但有无数种方法可以做到这一点.当你将前端框架带入混音时,它会变得更加有趣.

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

希望能为您解决问题!

  • 根据你的说法,我仍然不清楚为什么不推荐传统的IPC方式。如果我不使用任何框架(如 angular)怎么办? (3认同)