代码之家  ›  专栏  ›  技术社区  ›  Bolza

Angular属性装饰器仅为每个类类型创建一个属性实例

  •  3
  • Bolza  · 技术社区  · 8 年前

    最后,你可以这样使用装饰器

    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 回复  |  直到 8 年前
        1
  •  2
  •   Bolza    8 年前

    我将用思考一天后找到的解决方案来回答这个问题。

     return (target, key, descriptor) => {
    

    在里面

    return  function (target, key) {
    

    通过这种方式,我可以使用 this

    然后我必须找到一个好位置来初始化行为主题。在主属性的getter或setter中这样做是行不通的(我想访问 this.cats$ this.cats ).

    所以我用一个新的getter解决了这个问题 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);
                },
            });
        };
    }
    
    推荐文章