はじめに
とあるhtml5 + knockoutJSでつくられているシステム開発中、knockoutJSのifバインディングではまった。
※検証に用いたKnockout.jsのバージョンは 3.4.2 です。
きほんのきほう
公式ドキュメントのifバインディングを見て、一番単純な記法だとこんな感じ。
いつも見えてるやつだぜ!
<div data-bind="if: property.aTrueValue">
ifバインディングの評価値がtrueだったらでるぜ!
</div>
ko.applyBindings({
property: {
aTrueValue:ko.observable(true)
}
});
ふるまい
aTrueValueがtrue | aTrueValueがfalse | aTrueValueが存在しない |
---|---|---|
text表示 | text非表示 | text非表示 |
aTrueValueが無かったり、falseだったりするとちゃんとfalseとして評価される。ふんふん。
やべーうごき①~observableの中身で評価すると~
observableのオブジェクトでifバインディングの評価をするときほん編の通り想定通りの動きをしてくれるが、observable引数無の実体の値でifバインディングを使うと少し変な動きになる。
いつも見えてるやつだぜ!
<div data-bind="if: property.aTrueValue()">
ifバインディングの評価値がtrueだったらでるぜ!
</div>
ko.applyBindings({
property: {
aTrueValue:ko.observable(true)
}
});
ふるまい
aTrueValueがtrue | aTrueValueがfalse | aTrueValueが存在しない |
---|---|---|
text表示 | text非表示 | text表示 |
(2018/3/11 追記)ifバインディングはプロパティの有無まではbooleanで判定してくれるが、存在しない関数はエラーとなり、結果DOMが生成されてしまう!! |
やべーうごき②~複数項目の論理式~
複数のobservableオブジェクトでifバインディングの評価をするとへんてこになる。
いつも見えてるやつだぜ!
<div data-bind="if: (property.aTrueValue && property.anotherTrueValue)">
ifバインディングの評価値がtrueだったらでるぜ!
</div>
ko.applyBindings({
property: {
aTrueValue:ko.observable(true),
anotherTrueValue:ko.observable(true)
}
});
ふるまい
--- | aTrueValueがtrue | aTrueValueがfalse | aTrueValueが存在しない |
---|---|---|---|
anotherTrueValueがtrue | text表示 | text表示 | text非表示 |
anotherTrueValueがfalse | text非表示 | text非表示 | text非表示 |
anotherTrueValueが存在しない | text非表示 | text非表示 | text非表示 |
(2018/3/11 追記)javascriptの論理式について盛大に勘違いしてました。functionはtrue評価されてしまうので、後方のプロパティでifバインディングが効く模様。でもプロパティが存在しない場合はfalseになる。なかなか複雑。。。 |
やべーうごき③~複数項目の論理式with中身評価~
複数のobservableオブジェクトの中身で評価してみる。
いつも見えてるやつだぜ!
<div data-bind="if: (property.aTrueValue() && property.anotherTrueValue())">
ifバインディングの評価値がtrueだったらでるぜ!
</div>
ko.applyBindings({
property: {
aTrueValue:ko.observable(true),
anotherTrueValue:ko.observable(true)
}
});
ふるまい
--- | aTrueValueがtrue | aTrueValueがfalse | aTrueValueが存在しない |
---|---|---|---|
anotherTrueValueがtrue | text表示 | text非表示 | text表示 |
anotherTrueValueがfalse | text非表示 | text非表示 | text表示 |
anotherTrueValueが存在しない | text表示 | text非表示 | text表示 |
条件式の頭が存在しないと、trueなんだね!すっごーい!
(2018/3/11 追記)①と同様、存在しない関数はエラーとなるのと、ショートサーキット評価で上記仕様になっているみたい。
結論
ifバインディングを使う場合は
条件式のプロパティを定義したうえでobservableの中身で評価する
を守らないと想定通り動かなさそう。
参考
https://stackoverflow.com/questions/15307504/knockout-js-if-binding-on-multiple-booleans
http://kojs.sukobuto.com/docs/if-binding
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Logical_Operators