web-dev-qa-db-ja.com

Electronでフォームを処理する適切な方法は何ですか?

フォームhtmlおよび送信イベントは「レンダラー」の一部です。提出されたデータは、メインプロセスで利用可能である必要があります。フォームを送信し、main.jsでそのデータにアクセスできるようにする適切な方法は何ですか?

「リモート」モジュールを使用して、main.jsから関数にデータを渡すだけですか、それともより良いアプローチがありますか?

24
Elfy

サービス(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にメッセージを送り返すこともできます。

sync

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

またはasync

// 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;
});
11
Adam Eri

これを行う方法にはいくつかのバリエーションがありますが、すべては [〜#〜] ipc [〜#〜] を介して行われます。

IPC(プロセス間通信)は、レンダリングプロセスからメインプロセスにデータを取得する唯一の方法であり、イベント駆動型です。これが機能する方法は、イベントが発生したときにプロセスがリッスンして何かを返すカスタム定義のイベントを使用できることです。

@Adam Eriが述べている例は、ドキュメントにある ipcMainの例 のバリエーションですが、この方法はすべてに適合するサイズではありません。

それを言う理由は、メニュー(通常はメインプロセスで実行される)、またはVue =または角度。

いくつか例を挙げます。

WebContentsでRemoteを使用する

要するに、電子 リモート を使用できますが、フォームの目的には推奨されるアプローチではありません。ドキュメントに基づいて、リモートのポイントは

レンダラープロセスからメインプロセスモジュールを使用する

tl:dr-このプロセスは、その同期性のためにデッドロックを引き起こし、イベントオブジェクトリーク(ガベージコレクションによる)を引き起こし、コールバックで予期しない結果を引き起こす可能性があります。

詳細な説明はドキュメントから得ることができますが、最終的には、レンダリングプロセスで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を使用する

考えられる3番目のオプションは、メインプロセスからレンダラープロセスにアクセスするための webContents.executeJavascript です。 リモート ドキュメントセクションからのこの説明。

概要

ご覧のとおり、Electronでフォームを処理する方法にはいくつかのオプションがあります。 IPCを使用している限り、問題ありません。あなたがそれをどのように使用するかはあなたをトラブルに巻き込む可能性があります。フォームを処理するためのプレーンなJavaScriptオプションを示しましたが、それを行う方法は無数にあります。フロントエンドフレームワークをミックスに組み込むと、さらに興味深いものになります。

個人的には、可能な場合は従来のIPCアプローチを使用します。

それがあなたのために物事を解決することを願っています!

7
unseen_damage