SourceChord

C#とXAML好きなプログラマの備忘録。最近はWPF系の話題が中心です。

electron環境でknockout.jsを使ってみる

そういえば、ブログにメモしてなかったので、改めてφ(..)メモメモ
knockout.jsをelectron環境で使う手順についてメモしときます。

準備

プロジェクトの雛型

以前↓で書いた、Electron+TypeScriptなプロジェクトのテンプレートを雛型に利用します。
sourcechord/electron-typescript-sample · GitHub

まずは、このプロジェクト一式をcloneしてローカルに置いたところから始めます。

git clone https://github.com/sourcechord/electron-typescript-sample.git

knockout.jsのインストール

以下のコマンドで、npmからknockout.jsをインストールします。

npm install knockout --save

続けて、tsdを使って型定義ファイルをインストールします。

tsd install knockout -rosa

これで準備OK。

knockout.jsの読み込み

それでは、さっそくknockout.jsを使うために、ライブラリを読み込んでみます。
普通にブラウザ上からknockout.jsを使うときは、こんな風に<script>タグで読み込みをしていたと思います。 (↓node_modulesフォルダ内のファイルを直接指定する場合)

<script type="text/javascript" src="node_modules/knockout/build/output/knockout-latest.js"></script>

electronでknockout.jsを使う時には、このように<script>タグを使ったロードももちろんできます。

ですが、electron環境では、node.jsのモジュールシステムが利用できるので、CommonJSスタイルでのrequireができます。
ということで、こんな風に、javascript側から直接knockout.jsのスクリプトを普通にrequireして読み込むこともできます。
(ES6スタイルのimportで使う方が今風ですね。)

import ko = require('knockout');
//import * as ko from 'knockout';   // ES6スタイルのimportをする場合はこちら

browserifyやらWebPackやらのモジュール管理システムを使わずとも、直接node_module内のライブラリをrequireして使えるってのがなんか新鮮です。
scriptタグではなく、require/importで書いておけば、後々でWebPack使ってバンドルしたい、というときにもそのまま移行できそうです。

使ってみる

テキストボックス1つ作り、そこに入力した文字列をボタン押下時にalert表示するだけ、という単純なサンプルを作ってみます。
f:id:minami_SC:20160110161701p:plain:w350

ページの定義

やってることは↓だけです。 * index.jsを読み込む * inputタグ/buttonタグを配置 * ↑のタグに対してknockout.jsのデータバインドを色々設定

html側からは、knockout.jsの読み込みはしていません。

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <script src="index.js"></script>
  </head>
  <body>
    <h1>Knockout.jsのテスト</h1>
    <hr/>
    <span>名前:</span>
    <input type="text" data-bind="value: name"></input>
    <button data-bind="click: showName">Show Name</button>
  </body>
</html>

viewmodelクラスの作成

nameプロパティと、nameを表示するためのshowNameメソッドを持ったVMクラスを作り、onloadイベントでVMの設定をしているだけです。
また、knockout.jsはこのindex.ts側からimpoteしています。

index.ts

import * as electron from 'electron'; 
import {remote} from 'electron'; 
const app = remote.app;
const BrowserWindow = remote.BrowserWindow;
const dialog = remote.dialog;

import * as ko from 'knockout';

class SampleViewModel{
    public name: KnockoutObservable<string>
    = ko.observable<string>();
    
    public showName() {
        alert(`こんにちは、${this.name()}さん`);
    }
}

window.onload = () => {
    var vm = new SampleViewModel();
    ko.applyBindings(vm);
};

とりあえず今回はここまで。