2

我正在使用Property Decorator爲每個屬性創建一個具有靜態getter/setter的Observable。Angular Property Decorator只爲每個類類型創建一個屬性實例

最後,你可以使用裝飾用這種方式

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

    @ObservableProperty(DEFAULT_PIGS) 
    pigs: number; 
} 

用於裝飾的實際代碼是

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組件的一個實例。

但有兩個實例,這個測試實際上失敗了。

fdescribe('ObservableProperty Decorator',() => { 
    let test: Test; 
    let doppleganger: Test; 

    beforeEach(() => { 
     test = new Test(); 
     doppleganger = new Test(); 
    }); 

    it('should create different observables for each props',() => { 
     expect(test['cats$'] === doppleganger['cats$']).toBe(false); 
    }); 
}) 

由於裝飾器在組件實例的原型上工作,創建的變量完全相同。

我該如何解決這個問題?

如果無法用裝飾器完成什麼是一種優雅的替代方法?

回答

1

我打算用一天思考後找到的解決方案來回答問題。

首先,我無法訪問實例的主要問題是使用裝飾器定義中的箭頭函數。所以我改變:

return (target, key, descriptor) => { 

return function (target, key) { 

這樣我可以使用this的的getter/setter內訪問實例。

然後,我不得不找到一個好點來初始化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); 
      }, 
     }); 
    }; 
} 
相關問題