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); 
      }, 
     }); 
    }; 
} 
相关问题