2

問題

ノックアウトjsの作業と調査を行っていると、ある時点で行き詰まりました。ビューモデル (および基礎となるビューモデル) を JSON にシリアライズしたいと考えています。子ビューモデルには親ビューモデルを参照するプロパティがあるため、これは無限ループになります。この問題を解決するためのベスト プラクティスは何ですか?

コード

var Partner = function (parent) {
    var self = this;
    self.parent = parent;
    self.name = ko.observable('');
}

var ProjectViewModel = function () {
    var self = this;
    self.nr = ko.observable(0);
    self.tite = ko.observable('');
    self.partners = ko.observableArray();            

    self.addPartner = function () { self.partners.push(new Partner(self)) };
    self.removePartner = function (c) { self.partners.remove(c) };
};
var vm = new ProjectViewModel();
ko.applyBindings(vm);


$("#button").click(function () {
    alert(ko.toJSON(vm));
}

これまでに試したこと

Partner ビューモデルに次のメソッドを追加してみました。

Partner.prototype.toJSON = function () {
            var copy = ko.toJS(self);
            delete copy.parent;
            return copy;
        }

ProjectViewModel に複数のパートナーがある場合、これは 1 つのパートナーでのみ機能します。すべてのパートナーは最後のパートナーと同じ値になります。これは、JSON にシリアル化したい場合にのみ発生します。

4

1 に答える 1

2

この状況を処理するには、いくつかの方法があります。ko.toJSKOの部分はこれを適切に処理します。それは最終的に(エラーの原因となる後にJSON.stringify呼び出されます。ko.toJSko.toJSON

プロトタイプのtoJSONメソッドはかなり似ていますがthisself.

したがって、次のようになります。

Partner.prototype.toJSON = function() {
  var copy = ko.toJS(this);
  delete copy.parent;
  return copy; 
};

それを処理する他の方法:

1-実際には親を子オブジェクトに保存せず、コンストラクターに渡された引数に基づいてハンドラーで直接参照します。

var Partner = function (parent) {
    var self = this;
    self.name = ko.observable(name);

    self.doSomething = function() {
        //can use "parent" directly here without storing it anywhere
    };
};

2-親参照を「隠す」

var Partner = function (parent) {
    var self = this;
    self.meta = function() {};
    self.meta.parent = parent;
    self.name = ko.observable(name);    
};

関数の背後に値を配置できますparent(オブザーバブルのサブプロパティとして配置できます)。構造が によってプレーンな JS オブジェクトに変換されるko.toJSと、関数のサブプロパティはすべて失われます。

3- やりたいことに応じて、アプリケーションの構造を変更します。子の名前が変更されるたびに、親が対応したいとします。コールバックを渡し、サブスクリプションをセットアップし、変更されるたびに実行できます

var Partner = function (nameChangedCallback) {
    var self = this;
    self.name = ko.observable(name);    

    if (typeof nameChangedCallback == "function") {
        self.name.subscribe(function() {
           nameChangedCallback.call(self, self);
        });
    }
};
于 2013-01-16T20:15:35.303 に答える