10

私のテキストを見てください。配列のデータを計算するために、knockoutjsとforeachのobservableArrayを使用しようとしています。例1は正常に機能します。フィールドのデータを変更した場合に計算される合計。しかし、例2は機能していません。

<html>
<head>                                                                         
    <title></title>                                                            
    <script type='text/javascript' src='/js/jquery-1.8.2.min.js'></script>     
    <script type='text/javascript' src='/js/knockout-2.1.0.debug.js'></script> 
</head>                                                                        
<body>
<p>Example 1</p>
<div>
    <p>
    <input data-bind="value: fnum1" />
    <input data-bind="value: fnum2" />
    <span data-bind="text: ftotsum"></span>
    </p>
</div>    
<p>Example 2</p>
<div>
    <p>
    <!-- ko foreach: fields -->
    <input data-bind="value: $data" />
    <!-- /ko -->
    <span data-bind="text: ltotsum"></span>
    </p>
</div>
</body>
<script>
    function vm(){
        //Calc Example 1
        var self = this;
        self.fnum1 = ko.observable(1);
        self.fnum2 = ko.observable(2);
        self.ftotsum = ko.computed(function(){
            return parseFloat(self.fnum1()) + parseFloat(self.fnum2());
        });
        //Calc Example 2
        self.fields = ko.observableArray([1, 2]);
        self.ltotsum = ko.computed(function(){
            var total = 0;
            ko.utils.arrayForEach(self.fields(), function(item) {
                total += parseFloat(item);
            })
            return total;
        }); 
    };

    ko.applyBindings(new vm());
</script>
</html>
4

2 に答える 2

6

ドキュメントには次のように記載されています。

重要なポイント:observableArrayは、オブジェクトの状態ではなく、配列内にあるオブジェクトを追跡します

オブジェクトを単に observableArray に入れるだけでは、そのオブジェクトのすべてのプロパティ自体が監視可能になるわけではありません。もちろん、必要に応じてこれらのプロパティを監視可能にすることもできますが、それは独立した選択です。observableArray は保持しているオブジェクトを追跡し、オブジェクトが追加または 削除されたときにリスナーに通知します。

入力フィールドの値が配列内の値にバインドされていないため、2 番目の例は機能しません。配列内のその値はforeachバインディングで 1 回だけ使用されますが、入力ボックスに入力しても KO はトリガーされません。

これは、ソリューションが実装された実用的なフィドルです。助っ人を利用しましたObsNumber

function vm(){
    var self = this;

    var ObsNumber = function(i) {
        this.value = ko.observable(i);
    }

    self.fields = ko.observableArray([new ObsNumber(1) ,
                                      new ObsNumber(2)]);

    self.sum = ko.computed(function(){
        var total = 0;
        ko.utils.arrayForEach(self.fields(), function(item) {
            total += parseFloat(item.value());
        });
        return total;
    });
};

ko.applyBindings(new vm());

そして次のマークアップ

<div>
    <p>
    <!-- ko foreach: fields -->
    <input data-bind="value: $data.value" />
    <!-- /ko -->
    <span data-bind="text: sum"></span>
    </p>
</div>​
于 2012-10-01T19:55:51.050 に答える
6

編集:フィドルが機能しました。Raffaeleは、オブザーバブルをオブジェクト内にラップする必要があると言っていますが、配列作成自体の中でそれを行うことができます.ko.utilsを使用してオブザーバブルをアンラップするのが好きです。同じことを行いますオブザーバブルの場合ですが、オブザーバブル以外が渡された場合でもクラッシュしません。完全な例については、フィドルを参照してください。

observableArray は渡された値を観測可能にしません。これはよくある間違いです。observableArray は、値ではなく配列への変更を監視するだけです。配列内の値を監視可能にしたい場合は、そのようにする必要があります。

function vm(){
    //Calc Example 1
    var self = this;
    self.fnum1 = ko.observable(1);
    self.fnum2 = ko.observable(2);
    self.ftotsum = ko.computed(function(){
        return parseFloat(self.fnum1()) + parseFloat(self.fnum2());
    });
    //Calc Example 2
    self.fields = ko.observableArray([{"num":ko.observable(1)},{"num":ko.observable(2)}]);
    self.ltotsum = ko.computed(function(){
        var total = 0;
        ko.utils.arrayForEach(self.fields(), function(item) {
            total += parseFloat(ko.utils.unwrapObservable(item.num));
        });
        return total;
    }); 
};
ko.applyBindings(new vm());

上記の例で動作するはずです。

于 2012-10-01T19:54:04.717 に答える