0

ノックアウト js で次の問題を解決したいと考えています。3 つの入力があります。pricequantityおよびtotal、設定したい場所

 total = price * quantity 

priceまたはを更新するときquantity、また設定したい

 price = total / quantity 

私が更新する場合total

私はもともと計算されたオブザーバブルでこれを行いましたが、これはほとんど機能しませんでしたが、丸めに問題があります。たとえば、もしそうなら

quantity(3)
total(100)

私は 33.33 に設定したいのですpriceが、小数点以下 2 桁だけですが、totalそれでも 100 に設定する必要があるため、IDtotal = price * quantityは保持されません。

私が取った計算された観測可能なアプローチでは、totalこの場合は 99.99 に設定されます。これが、この状況が docs の fullname/firstname/lastname の例と異なる理由です

基本的にprice/totalフィールドは相互に再帰的です。手動でサブスクライブする以外に、この問題への適切なアプローチを見つけることができませんが、これは非常に単調に感じられ、一連のサブスクリプションなどを手動で処理する必要があることを意味します.

4

2 に答える 2

3

「実際の値」の ko.observables (つまり、数量、価格、および合計) を作成し、フォーム フィールドでフォーカス イベントを追跡し、ko.computed() を使用して再計算することで、同様のことを行いました (ただし、現在のフィールドが選択されている場合)、フォームの値を書式設定します。

この 1 文の説明は複雑に聞こえますが、コード的にはそれほど複雑ではありません。

JavaScript:

var Model = function () {
    var self = this;

    self.quantity = ko.observable(0);
    self.price = ko.observable(0);
    self.price.selected = ko.observable(false);
    self.total = ko.observable(0);
    self.total.selected = ko.observable(false);

    self.formattedPrice = ko.computed({
        read: function () {
            if (!self.price.selected()) {
                 var total = self.total() || 0;
                 var quantity = self.quantity() || 0;
                 var value = total / quantity;
                 self.price(isNaN(value) ? 0 : value);
            }
            return '$' + self.price().toFixed(2);
        },
        write: function (value) {
            value = parseFloat(value.replace(/[^\.\d]/g, ""));
            self.price(isNaN(value) ? 0 : value);
        }
    });

    self.formattedTotal = ko.computed({
        read: function () {
            if (!self.total.selected()) {
                var quantity = self.quantity() || 0;
                var price = self.price() || 0;
                var value = quantity * price;
                self.total(isNaN(value) ? 0 : value);
            }
            return '$' + self.total().toFixed(2);
        }, 
        write: function (value) {
            value = parseFloat(value.replace(/[^\.\d]/g, ""));
            self.total(isNaN(value) ? 0 : value);
        }
    });
};

ko.applyBindings(new Model());

HTML では、次のように価格と合計をバインドします。

<input data-bind="value: formattedPrice, hasfocus: price.selected" />

<input data-bind="value: formattedTotal, hasfocus: total.selected" />

実際の例を見たい場合は、 jsfiddleでコーディングしてください。

于 2013-06-06T18:28:35.440 に答える
0

答えてくれてありがとう。参考までに、これが私が現在持っている解決策です。問題が発生しない限り、それに固執する可能性があります。

    var self = this;
    this.price = ko.observable().extend({numeric: 2});
    this.quantity = ko.observable(1).extend({ numeric: 2 });
    this.total = ko.observable(1).extend({ numeric: 2 });

    var unsub_total = this.total.subscribe(function (total) {
        if (self.quantity() != 0)
            self.price(total / self.quantity())
    });

    // setting quantity will update both price and total
    var unsub_qty = this.quantity.subscribe(function (qty) {
        self.total(self.price() * qty);
    });

    var unsub_price = this.price.subscribe(function (price) {
        self.total(price * self.quantity());
    });

    this.unsub = function() { unsub_total(); unsub_price(); unsub_qty(); };
于 2013-06-08T21:07:23.747 に答える