初心者向き!Electronで親ウィンドウ↔子ウィンドウのデータ送信

さてさて、これまでこのブログではいくつか「ウェブの技術でデスクトップアプリ」を作ることができるElectronの記事を公開してきました。

そして、それらの記事では「●●というアプリをつくる」というコンセプトが多かったのですが、たまには技術的なテーマも取り扱った記事を書きたくなったので今回の話題は少しいつもとは違ったものにしました。

そのテーマとは、

  • 親ウィンドウ ➜ 子ウィンドウへ
  • 子ウィンドウ ➜ 親ウィンドウへ

それぞれデータを送信、受信する方法です。

Electronは起動するとまず親ウィンドウが表示されます。そして、そのウィンドウからはいくつでも子ウィンドウを開くことができるのですが、たまに別ウィンドウをリモートコントロールしたくなるときがあります。

そんなときは今回紹介する方法で実行してみてくださいね。
(最後に教材ソースコードがダウンロードできます)

※ 開発環境: Electron 2.0

Electronのインストール

インストールは、初心者向き!electron で簡単なメモ帳をつくってみよう“electronのインストール” に詳しく書いてあるので、そちらを見てください。

フォルダ名はparent-child-windowです。

main.jsでアプリの設定

今回はそれほどしっかりしたレイアウトは必要ありませんので親ウィンドウサイズは小さめにしています。

また、メニューバーは非表示にします。

function createWindow () {
    
    mainWindow = new BrowserWindow({
        width: 300,
        height: 300,
        autoHideMenuBar: true
    })

    // 省略

※ 重要

なお、今回は親子関係のウィンドウを扱うテーマなので、いつものようにindex.htmlではなくparent.htmlを使います。そのため、同じくmain.js内の以下の部分を変更しておいてください。

mainWindow.loadFile('index.html')

↓↓↓ 変更します

mainWindow.loadFile('parent.html')

子ウィンドウを開くコードをつくる

では、まずは親ウィンドウから子ウィンドウを開くコードです。

レイアウトをつくる

parent.htmlを作成してHTMLコードを次のように保存します。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>親ウィンドウ</title>
</head>
<body style="background:#fdd;">
    <div id="app">
        <h1>ここは親ウィンドウです</h1>
        <button type="button">子ウィンドウを開く</button>
    </div>
    <script>
        require('./renderer.js')
    </script>
</body>
</html>

実行するとこのようになります。
(子ウィンドウとの区別がつきやすいようにテーマカラーは赤です)

JavaScriptで子ウィンドウを開く

ではボタンがクリックされたら子ウィンドウを開くコードを作っていきましょう。
まずはクリックイベントをボタンに設定します。

<button type="button" @click="openChildWindow()">子ウィンドウを開く</button>

そして、openChildWindow()の中身です。
今回はシンプルにwindow.open()でウィンドウを開きましょう。

methods: {
    openChildWindow() {

        const url = 'child.html'
        window.open(url, '', 'width=300,height=300')

    }
}

ちなみにwindow.open()の第3引数でウィンドウサイズを指定しています。

なお、まだchild.htmlは作成していませんので次のようなコードで保存してください。(テーマカラーは青です)

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>子ウィンドウ</title>
</head>
<body style="background:#ddf;">
    <div id="app">
        <h1 style="color:#007;">ここは子ウィンドウです</h1>
    </div>
    <script>
        require('./renderer.js')
    </script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
    <script>

        new Vue({
            el: '#app'
        })

</script>
</body>
</html>

では実際に親ウィンドウから子ウィンドウを開いてみましょう。

うまくいきました。
では次からこの2つのウィンドウを使ってデータの送受信をしてみましょう。

親➜子へデータ送信する

『親からの送信データ』というテキストを子ウィンドウへ送信し、それをアラートで表示してみましょう。

まずは、parent.html編集していきます。

子ウィンドウを変数へ格納する

まずは開いたウィンドウにいつでもアクセスできるよう、datachildWindowという変数を作ります。

data: {
    childWindow: null
},

そして、先ほどのwindow.open()の部分でウィンドウを格納。

openChildWindow() {

    const url = 'child.html'
    this.childWindow = window.open(url, '', 'width=300,height=300')

}

これでいつでも子ウィンドウへアクセスできるようになりました。

子ウィンドウへデータ送信する

次に子ウィンドウへデータ送信する部分です。

クリックイベントをつけたボタンをつくり、sendToChild()が実行できるようにします。

<button type="button" @click="sendToChild()">子ウィンドウへデータ送信</button>

sendToChild()の中身はこうなります。

sendToChild() {

    const message = '親からの送信データ'
    this.childWindow.postMessage(message);

}

これで子ウィンドウへデータ送信することができます。

子ウィンドウでデータを受け取る

では、親ウィンドウから送信されたデータを子ウィンドウで取得してみましょう。

ここからは、child.htmlを編集していきます。

データの取得はmessageイベントを通して行いますので、コードは次のようになります。

new Vue({
    el: '#app',
    mounted() {

        window.addEventListener('message', (e) => {

            alert(e.data)

        })

    }
})

テストしてみる

では実際に親ウィンドウ➜子ウィンドウへデータを送信してみます。

まずは親ウィンドウから子ウィンドウを開きます。

そして、「子ウィンドウへデータ送信」ボタンをクリックすると・・・・・・

親からの送信されたテキストがアラート表示されました。
成功です。

子➜親へデータ送信する

では、次に子ウィンドウから親ウィンドウへデータ送信する方法を見てみましょう。
送信するテキストは『親からの送信データ』です。

まずはchild.htmlを編集していきます。

親ウィンドウへデータ送信する

親ウィンドウへ送信するボタンをつくり、sendToParent()を実行できるようにします。

<button type="button" @click="sendToParent()">親ウィンドウへデータ送信</button>

sendToParent()の中身はこうなります。

methods: {
    sendToParent() {

        const message = '子からの送信データ'
        window.opener.postMessage(message)

    }
}

親ウィンドウでデータを受け取る

では、子ウィンドウから送信されたデータを親ウィンドウで取得する方法です。

ファイルは、parent.htmlです。

データの送信は先ほどと同じくmessageイベントで取得できるよう次のようなコードになります。

mounted() {

    window.addEventListener('message', (e) => {

        alert(e.data)

    })

}

テストしてみる

では、最後にテストしてみましょう。
親ウィンドウから子ウィンドウを開きます。

そして、子ウィンドウにある「親ウィンドウへデータ送信」ボタンをクリックします。

すると親ウィンドウへデータ送信され、さらにアラート表示されました。
成功です。

ちなみに

postMessageで送信できるのはテキストだけではなく、配列やオブジェクトも送信することができます。

そのため、次のようにオブジェクトを送信し、typeなどの追加データで切り替えをすれば様々なデータ送信を実現することができます。

// parent.html

this.childWindow.postMessage({
    type: 'alert',
    message: 'メッセージ'
})
// child.html

window.addEventListener('message', (e) => {

    const type = e.data.type

    if(type == 'alert') { // アラート表示する

        alert(e.data.message)

    } else if(type == 'close') { // ウィンドウを閉じる

        window.close()

    }

})

お疲れ様でした!

教材ソースコードをダウンロードできます

今回実際に開発したソースコード一式を以下からダウンロードすることができます。

Electronで親ウィンドウ↔子ウィンドウへデータ送信

おわりに

ということで今回は、Electronで親子ウィンドウ間のデータ送信をお届けしました。

ちなみに、分かりやすくするために今回は「データ送信」という表現にしていますが、必ずデータ送信しないといけないわけではなく、ただ単に親ウィンドウでクリックしたら子ウィンドウにある特定のメソッドを実行する、なんて使い方もできますので使いみちは多種多様にあるのではないでしょうか。

しかも、それほどコード量が多くなくても実行できますので覚えておいて損はしないと思います。

ぜひ参考にしてみてくださいね。

ではでは〜。