谁使用过typescript Decorators特性?

本来想利用装饰者来监听数据更改. 代码如下:

export function fireBind(type:string) {

        return function (taget:any, key:string, descriptor:TypedPropertyDescriptor<any>)            {
            let oldSet = descriptor.set;
            descriptor.set = function(val){
                MessageCenter.fire(new ModelEvent(type, val));
                console.log('1111');
                oldSet.call(null, val);
                console.log('2222');
            }
        }
    }

class Test {
    private _selected;

    @fireBind(EventState.GOODS_SELECTED)
    public set selected(data:any) {
        this._selectedData = data;
        console.log('this._selectedData:', this._selectedData);
    }


    public get selected(){
         return this._selectedData;
  }
}

调用 :


const T = new Test();
T.selected = 'test';
console.log(T.selected);

输出结果:
1111
this._selectedData: test
null;


结果就是 调用的时候可以正常设置值, 但是立即获取selected时确为空了...... 谁遇到过啊. 怎么破?
感谢..

阅读 3.4k
3 个回答

这样改改吧:

export function fireBind(type: string) {

    return function(taget: any, key: string, descriptor: TypedPropertyDescriptor<any>) {
        let oldSet = descriptor.set;
        descriptor.set = function(val) {
            MessageCenter.fire(new ModelEvent(type, val));
            console.log('1111');
            oldSet.call(taget, val);
            console.log('2222');
        }
    }
}

class Test {
    private _selectedData;

    @fireBind(EventState.GOODS_SELECTED)
    public set selected(data: any) {
        this._selectedData = data;
        console.log('this._selectedData:', this._selectedData);
    }


    public get selected() {
        return this._selectedData;
    }
}
const T = new Test();
T.selected = 'test';
console.log(T.selected);

我没写过 typescript ,所以我编译成js看了下:

function fireBind(type) {
    return function (taget, key, descriptor) {
        var oldSet = descriptor.set;
        descriptor.set = function (val) {
            MessageCenter.fire(new ModelEvent(type, val));
            console.log('1111');
            oldSet.call(null, val);
            console.log('2222');
        };
    };
}
exports.fireBind = fireBind;
var Test = (function () {
    function Test() {
    }
    Object.defineProperty(Test.prototype, "selected", {
        get: function () {
            return this._selectedData;
        },
        set: function (data) {
            this._selectedData = data;
            console.log('this._selectedData:', this._selectedData);
        },
        enumerable: true,
        configurable: true
    });
    __decorate([
        fireBind(EventState.GOODS_SELECTED)
    ], Test.prototype, "selected");
    return Test;
}());
var T = new Test();
T.selected = 'test';
console.log(T.selected);

这里面第一步是 T 实际上是 未执行的 Test,但是 Test 通过 Object.defineProperty 解决自身的 this 的问题,类似于 bind,
然后通过 __decorate,将 Test.prototype, "selected" 两个参数传给 fireBind(EventState.GOODS_SELECTED),到这里没什么问题。
第二步是执行 T.selected = 'test';,也就是原型链上的 set,从代码上看 fireBind 中 return func 的第三个参数 descriptor 并没有传入进来,
这里先假定传参进来了, __decorate 的执行结果为 console.log('1111');T.selected = 'test'; 的结果为console.log('this._selectedData:', this._selectedData);,先抛开这个问题,
所以可能代码不全吧,fireBind 函数中的 taget ==> Test.prototype 还有 key ==> "selected" 和 descriptor 没有关联,不好分析

oldSet.call(null, val);
=>
oldSet.call(descriptor, val);

试试? 注意this的值, 可以console.log(this)出来

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题