4

私はKO(2日前に開始)に比較的慣れておらず、いくつかの簡単な例を試していました。現在、このコードに問題があります。

<div id="idChangeStyle">
    <span data-bind="style: { background: GetAge() < 18 ? 'red':'white'}">Enter Your Age:</span>
    <input type="text" data-bind="value: GetAge"></input>
</div>
function ageViewModel() {
    var self = this;
    self.age = ko.observable(18);
    self.GetAge = ko.computed({
        read: function () {
            return self.age();
        },
        write: function (value) {
            value = parseInt(String(value).replace(/[^\d]/g, ""));
            if (isNaN(value))
                self.age(18);
            else
                self.age(value);
        }
    });
};
ko.applyBindings(new ageViewModel(), document.getElementById('idChangeStyle'));

http://jsfiddle.net/WJZqj/

基本的に、アプリは単一の入力(年齢)を取ります。INTEGERへの入力を解析するために書き込み可能な計算されたobservableを使用しており、そのNaNを解析した後、年齢をデフォルト値、つまり18に設定しようとしています。また、HTMLに単純なロジックがあり、スパンの背景を赤に変更しています。年齢が18歳未満の場合。

通常の場合は正常に動作しますが、問題が発生した場合は次のようになります。-

Case 1:
Current Input: 18 (initial case) 
enter *4* then tab //works
enter *a* then tab //work (defaults to 18) 
enter *a* then tab //doesn't work

case 2:
current input: 18 
enter *a *then tab* //*doesn't work

ノックアウトのコードをチェックして、次のコードを実行した場合に何が起こるかを確認しました:-

if(isNaN(value))
   self.age(18);

..次の行で:-

// Ignore writes if the value hasn't changed
if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) { 

_latestValueとの両方がarguments[0]同じ値(18)であるため、何も実行されません。年齢の値が変更されていないため、viewmodelプロパティとUIが同期していません。

これは私が間違っているからですか?

4

3 に答える 3

2

問題は、オブザーバブルに同じ値を入力した場合、それが値の変更とは見なされず、サブスクライバーに通知されないことです。エラー状態を連続して複数回入力した場合18、最初は設定された経過時間であり、再度設定された場合、変更イベントは発生しません。

そうは言っても、それを修正するには、サブスクライバーに手動で通知する必要があります。valueHasMutated()observableを呼び出すことで簡単にそれを行うことができます。

self.GetAge = ko.computed({
    read: function () {
        return self.age();
    },
    write: function (value) {
        value = parseInt(String(value).replace(/[^\d]/g, ""));
        if (isNaN(value)) self.age(18);
        else self.age(value);
        self.age.valueHasMutated(); // notify subscribers
    }
});
于 2013-03-26T22:08:02.697 に答える
2

ノックアウト3.0を使用した場合も、同じ状況になります。しかし、これらのトリックは私を助けません。なぜなら、計算されたプロパティ値が変更されたときにのみノックアウトが通知するからです。

そして私は問題を修正します:1)通知のみを使用します:常に

function ageViewModel(data) {
    //notify will should be always, because age is a primitive type  
    this.age = ko.observable(data.age).extend({notify: "always"});
    this.GetAge = ko.computed({
        read: function () {
            // notify will  should be always, because computed return values of a primitive type.
            return this.age();
        },
        write: function (value) {
            value = parseInt(String(value).replace(/[^\d]/g, ""));
            if (isNaN(value)) {
                this.age(18);
            }
            else this.age(value);

        },
        owner: this
    }).extend({notify: "always"});

};

2)notify:alwaysとknockout.mappingを使用します

function ageViewModel(data) {
    ko.mapping.fromJS(data, {}, this);
    //notify will should be always, because age is a primitive type  
    this.age = this.age.extend({notify: "always"});
    this.GetAge = ko.computed({
        read: function () {
            // notify will  should be always, because computed return values of a primitive type.
            return this.age();
        },
        write: function (value) {
            value = parseInt(String(value).replace(/[^\d]/g, ""));
            if (isNaN(value)) {
                this.age(18);
            }
            else this.age(value);

        },
        owner: this
    }).extend({notify: "always"});

};
于 2014-11-05T19:53:24.997 に答える
0

これを回避する簡単な方法は、年齢を0に設定してから、デフォルトに戻すことです。

つまり、次のように変更します。

if(isNaN(value)) {
    self.age(0);
    self.age(18);
}

ノックアウトが「正しい」方法であると見なされるかどうかはわかりませんが、おそらくそれが私が行うことです。

于 2013-03-26T21:34:38.147 に答える