しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

knockout.js の注意すべき点

相変わらず knockout.js でクライアントサイドコードを全力で書いてる男です。

最近、ちょっとした点でデバッグに時間をかけてしまったり、無駄なコードを書いてしまうことがあったので忘れないためにメモしておきます。

値の取得、設定は関数呼び出し

もう基本中の基本なんですが割と間違えます。例えば以下のようなコードを書いてしまったり。

// VM を作成
var viewModel = {
    name: ko.observable(),
    items: ko.observableArray()
};

// name は ko.observable なので NG
alert(viewModel.name);

// 同じく ko.observable なので NG
viewModel.name = "ほげほげ";

// items は ko.observableArray なので NG
alert(viewModel.items[0]);

// 同じく ko.observableArray なので NG
viewModel.items[0] = "ほげほげ";

ついついやってしまって動かないと悩むことになります。正しくは以下のように書きます。

// VM を作成
var viewModel = {
    name: ko.observable(),
    items: ko.observableArray()
};

// name を関数として呼び出す
alert(viewModel.name());

// 同じく引数を与えて呼び出す
viewModel.name("ほげほげ");

// items を関数として呼び出して配列を取得
alert(viewModel.items()[0]);

// 同じく関数として呼び出して配列に値を設定
viewModel.items()[0] = "ほげほげ";

完全にプロパティとして動作してくれたら最高に便利なんですが、相変わらず古い IE がネックらしいです。

バインド式の内部で条件式を使う場合

visible バインディングや if バインディングでは条件式を指定することが出来ます。普通に考えると使えないとおかしいですよね。

しかし、ここにさっきと同様の罠があります。例えば以下のように書いてしまうと正しく動きません。

<!-- value が 10 以上の場合だけ表示したい -->
<!-- ko: if value > 10 -->
<span>OK</span>
<!-- /ko -->

何故動かないのか想像がついた人もいると思います。そうです、条件式を使う場合には関数として呼び出して値を取得する必要があるからです。

例えば value が bool 値の場合は

<!-- ko: if value -->
<span>OK</span>
<!-- /ko -->

だけで正しく動作するので混乱してしまいがちです。主に私が。

なので正しくは以下のように書きます。

<!-- value が 10 以上の場合だけ表示する -->
<!-- ko: if value() > 10 -->
<span>OK</span>
<!-- /ko -->

これで期待した通りの挙動になってくれます。