6

サービスから戻ってくる一連のアイテムがあります。Item インスタンスごとに計算されたオブザーバブルを定義しようとしているので、本能的にそれをプロトタイプに配置するように指示されます。

計算されたオブザーバブルの 1 つのケース: システムはポイントを計算しますが、ユーザーは計算された値をオーバーライドすることを選択できます。ユーザーがオーバーライドを削除した場合に備えて、計算された値を利用できるようにしておく必要があります。また、ユーザーが割り当てたポイントと計算されたポイントを合体させ、合計を合計する必要があります。

マッピングを使用して次のことを行います。

var itemsViewModel;
var items = [
    { 'PointsCalculated' : 5.1 },
    { 'PointsCalculated' : 2.37, 'PointsFromUser' : 3 }
];

var mapping = {
    'Items' : {
        create : function(options) {
            return new Item(options.data);
        }
    }
};

var Item = function(data) {
    var item = this;
    ko.mapping.fromJS(data, mapping, item);
};

Item.prototype.Points = function () {
    var item = this;
    return ko.computed(function () {
        // PointsFromUser may be 0, so only ignore it if the value is undefined/null
        return (item.PointsFromUser != null) ? item.PointsFromUser : item.PointsCalculated;
    });
};

ko.mapping.fromJS(items, mapping, itemsViewModel);

現在の動作方法では、無名関数を呼び出して、計算されたオブザーバブルを返す必要があります。これは、バインディングごとに計算されたオブザーバブルの新しいインスタンスを作成するように見えます。これは、プロトタイプに配置するという点のほとんどを無効にします。また、オブザーバブルにアクセスするたびに使用する括弧の数を解読しなければならないのは少し面倒です。

また、やや壊れやすいです。コードで Points() にアクセスしようとすると、できません

var points = 0;
var p = item.Points;
if (p && typeof p === 'function') {
    points += p();
}

item ではなく、Points() のコンテキストが DOMWindow に変更されるためです。

マッピングに create() で計算されたものを配置すると、コンテキストをキャプチャできますが、各オブジェクト インスタンスにメソッドのコピーが存在します。

Michael Best の Google グループへの投稿 ( http://groups.google.com/group/knockoutjs/browse_thread/thread/8de9013fb7635b13 ) を見つけました。プロトタイプは、「アクティブ化」時に新しい計算されたオブザーバブルを返します。「アクティブ化」(おそらく Objs ?) と呼ばれるものはわかりませんが、オブジェクトごとに 1 回発生すると推測しており、「これ」がどのスコープを取得するかはわかりません。

この時点で、私は公開されたドキュメントで利用できるものを過ぎていると思いますが、ソースから何が起こっているのかを解読するためにまだ取り組んでいます.

4

3 に答える 3

7

JavaScriptクラスの各インスタンスに関数のインスタンスを持たせたくないと言われていますがko.computed、それはkoの機能がどのように構築されているかでは実際には機能しません。内部のプライベート変数への特定のメモリ ポインタを使用ko.computedまたはko.observable作成する場合、通常はクラス インスタンス間で共有することは望ましくありません (ただし、まれにそうなる場合があります)。

私はこのようなことをします:

var Base = function(){
    var extenders = [];

    this.extend = function(extender){
        extenders.push(extender);
    };

    this.init = function(){
        var self = this; // capture the class that inherits off of the 'Base' class

        ko.utils.arrayForEach(extenders, function(extender){

             // call each extender with the correct context to ensure all
             // inheriting classes have the same functionality added by the extender
             extender.call( self );
        });
    };
};

var MyInheritedClass = function(){
    // whatever functionality you need

   this.init(); // make sure this gets called
};

// add the custom base class
MyInheritedClass.prototype = new Base();

次に、計算されたオブザーバブル( your の各インスタンスのインスタンス関数である必要があります)については、次のようMyInheritedClassに宣言します。extender

MyInheritedClass.prototype.extend(function(){

     // custom functionality that i want for each class 
     this.something = ko.computed(function() {
         return 'test';
     });
});

あなたの例と上記で定義されたクラスを考えると、Base簡単に行うことができます:

var Item = function(data) {
    var item = this;

    ko.mapping.fromJS(data, mapping, item);

    this.init(); // make sure this gets called
};
Item.prototype = new Base();

Item.prototype.extend(function () {
    var self = this;

    this.Points = ko.computed(function () {

        // PointsFromUser may be 0, so only ignore it if the value is undefined/null
        return (self.PointsFromUser != null) ? 
               self.PointsFromUser : self.PointsCalculated;
    });
};

次に、Itemクラスのすべてのインスタンスにプロパティがあり、インスタンスごとにロジックPointsを正しく処理します。ko.computed

于 2012-04-25T00:56:11.773 に答える
0
Item.prototype.Points = function () {
var item = this;
return ko.computed(function () {
    // PointsFromUser may be 0, so only ignore it if the value is undefined/null
    return (item.PointsFromUser != null) ? item.PointsFromUser : item.PointsCalculated;
});

};

于 2015-02-13T13:58:31.437 に答える
0
Item.prototype.extend(function () {
var scope = this
this.Points = ko.computed(function () {
    return (this.PointsFromUser != null) ? 
           this.PointsFromUser : this.PointsCalculated;
}, scope);
};
于 2015-02-13T14:06:12.850 に答える