2

プロパティデコレータを使用して、すべてのプロパティに対して静的ゲッタ/セッタを持つObservableを作成しています。最後に角度プロパティデコレータは、クラスタイプごとに1つのプロパティインスタンスしか作成しません。

あなたはデコレータの実際のコードは

export function ObservableProperty(defaultValue = null): any { 
    return (target, key, descriptor) => { 
     const accessor = `${key}$`; 
     target[accessor] = new BehaviorSubject(defaultValue); 

     return Object.assign({}, descriptor, { 
      get: function() { 
       return this[accessor].getValue(); 
      }, 
      set: function(value: any) { 
       this[accessor].next(value); 
      }, 
     }); 
    }; 
} 

今、すべてがTestコンポーネントの1つのインスタンスを正常に動作され、このように

class Test { 
    @ObservableProperty(DEFAULT_CATS) 
    cats: number; 

    @ObservableProperty(DEFAULT_PIGS) 
    pigs: number; 
} 

をデコレータを使用することができます。

しかし、2つのインスタンスでは、このテストは実際には失敗します。

デコレータはコンポーネントインスタンスのプロトタイプで動作するため、作成された変数はまったく同じものです。

この問題を回避するにはどうすればよいですか?

デコレータではできない場合は、何がエレガントな代替方法ですか?

答えて

1

私は、1日の思考の後に見つけた解決策で質問に答えるつもりです。

最初に、私がインスタンスにアクセスできない主な問題は、デコレータの定義で矢印関数を使用していたことです。だから私は変更:

return (target, key, descriptor) => { 

return function (target, key) { 

私はthisを使用してゲッター/セッターの内側からインスタンスにアクセスすることができました。この方法

に。

次に、私はBehaviourSubjectを初期化する良い場所を見つけなければなりませんでした。ゲッタやセッターのメインプロパティの作業をするつもりはなかった(私はthis.catsにアクセスすることなくthis.cats$にアクセスしたい)。

私はcats$の新しいゲッターで解決しました。変数は秘密のプロパティに格納され、存在しない場合は作成されます。

ここに最終コードがあります。

export function ObservableProperty(defaultValue = null): any { 
    return function (target, key) { 
     const accessor = `${key}$`; 
     const secret = `_${key}$`; 

     Object.defineProperty(target, accessor, { 
      get: function() { 
       if (this[secret]) { 
        return this[secret]; 
       } 
       this[secret] = new BehaviorSubject(defaultValue); 
       return this[secret]; 
      }, 
      set: function() { 
       throw new Error('You cannot set this property in the Component if you use @ObservableProperty'); 
      }, 
     }); 

     Object.defineProperty(target, key, { 
      get: function() { 
       return this[accessor].getValue(); 
      }, 
      set: function (value: any) { 
       this[accessor].next(value); 
      }, 
     }); 
    }; 
} 
関連する問題