LoginSignup
2
3

More than 5 years have passed since last update.

【KnockoutJS】View で一時変数を使う

Last updated at Posted at 2014-05-23

KnockoutJS で WPF の Converter 的なこと (※参考) をやろうとした時、View のコンテキストに一時変数を定義できればいいな、と思いカスタムバインディングを作ってみました。

View 側で変換した値を使いまわしたい、というときに便利です。

できること

基本

※doSomething という関数がグローバルに定義されているとします

View
<div data-bind="variable: { foo: doSomething(someProperty) }">
    <!--ko if: foo() == 'hoge'-->
    <span data-bind="text: foo"></span>
    <!--/ko-->
</div>

このように一時変数が使えます。
ただし someProperty が observable の場合、変更が自動的に反映されません。
反映されるようにするには次のように書きます。

変更を自動反映する書き方

※ someProperty が observable になったとします

View
<div data-bind="variable: { foo: function(){ return doSomething(someProperty()) } }">
    <!--ko if: foo() == 'hoge'-->
    <span data-bind="text: foo"></span>
    <!--/ko-->
</div>

このように無名関数でラップし、getter 関数にすることによって
定義される一時変数を computed にすることができます。
結果、someProperty が書き換わると自動的に反映されるようになります。

Virtual Element

View
<!--ko variable: { foo: function(){ return doSomething(someProperty()) } }-->
    <!--ko if: foo() == 'hoge'-->
    <span data-bind="text: foo"></span>
    <!--/ko-->
<!--/ko-->

仮想エレメント(コメント記法)でも使えます。

Knockout-ES5 に対応してます

Knockout-ES5 はプロパティを () なしで参照できるようにしてくれるシンタックスプラグインです。
Knockout-ES5 が読み込まれている場合は以下のように書くことができます。

View
<div data-bind="variable: { foo: function(){ return doSomething(someProperty) } }">
    <!--ko if: foo == 'hoge'-->
    <span data-bind="text: foo"></span>
    <!--/ko-->
</div>

DEMO

http://jsfiddle.net/sukobuto/wpD2u/
コンバータパターンで一時変数を有効活用する例です。

variable-binding

これを ko.applyBindings 呼び出し前のどこかに貼り付ければ使えます。

variable-binding
ko.bindingHandlers['variable'] = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var variables = valueAccessor();
        for ( var v in variables ) {
            if (variables.hasOwnProperty(v)) {
                if (ko.isObservable(variables[v])) {
                    bindingContext[v] = variables[v];
                } else if (typeof variables[v] === 'function') {
                    if (ko.hasOwnProperty('defineProperty'))
                        ko.defineProperty(bindingContext, v, variables[v]);
                    else bindingContext[v] = ko.computed(variables[v]);
                } else {
                    bindingContext[v] = variables[v];
                }
            }
        }
    }
};
ko.virtualElements.allowedBindings['variable'] = true;
2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3