【问题标题】:Bind this when using method decorators in React在 React 中使用方法装饰器时绑定 this
【发布时间】:2017-04-11 16:02:50
【问题描述】:

如何绑定thistransform-decorators-legacy Babel 插件? 例如,我有一些简单的装饰器。装饰器工作,但 this 在组件的方法上未定义。

fucntion myDecorator(target, name, descriptor) {
    var oldValue = descriptor.value;

    descriptor.value = function() {
        ...// Doing some stuff here I need the decorator for
        ...// (for example logging on every method call)
        return oldValue.apply(null, arguments);
    };

    return descriptor;

}

class MyClass extends React.Component {
    @myDecorator
    myMethod() {
        ...// this.props... is unavailable here(`this` is undefined)
    }
}

如果我尝试将 @myDecorator 与一些 @autobind 装饰器一起使用,我会得到 TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute,因为

数据描述符是具有值的属性,该值可能是可写的,也可能是不可写的。访问器描述符是由一对 getter-setter 函数描述的属性。描述符必须是这两种风格之一;不能两者兼有。

在我的示例中,我不能使用 value()get()

在构造函数 (this.myMethod = thid.myMethod.bind(this)) 中绑定似乎也没有帮助,因为您绑定了未修饰的方法。

【问题讨论】:

    标签: javascript reactjs decorator ecmascript-next


    【解决方案1】:

    这就是我设法解决这个问题的方法: 使用提到的 @autobind 装饰器中的代码:

    function myDecorator(target, key, descriptor) {
        let fn = descriptor.value;
    
        return {
            configurable: true,
    
            get() {
                let boundFn = fn.bind(this);
                Reflect.defineProperty(this, key, {
                    value: boundFn,
                    configurable: true,
                    writable: true
                });
    
                return function() {
                    ...// Doing some stuff here I need the decorator for
                    ...// (for example logging on every method call)
                    return boundFn.apply(this, arguments)
                };
            }
        };
    }
    

    【讨论】:

    • 我不认为这是必要的,你可以这样做:var oldValue = descriptor.value; descriptor.value = function() { return oldValue.apply(this, arguments); } return descriptor;检查我的答案中的小提琴。
    • 这是因为您在示例的构造函数中第一次绑定到 this。这不适用于需要参数的装饰器。
    【解决方案2】:

    这不是.binding 装饰方法的问题吗?

    但是你错过了一些东西。即使您在constructor 中对类执行了.bindmyMethod,但当您调用它时,无论从哪里调用,myDecorator 都会修改执行范围。

    oldValue.apply(null, arguments)

    基本上,您将目标范围 (MyClass) 替换为 null

    所以你想要的是这样的:

    oldValue.apply(this, arguments)

    看到这个小提琴:http://jsfiddle.net/free_soul/0n6v1dtp/

    【讨论】:

    • 按照你的建议做,this 指向React.Component 而不是MyClass
    • 嗯,似乎有效。有趣的是,我 100% 确定我已经尝试过相同的方法但它不起作用,thisundefined。你能解释一下为什么需要props = this.props这一行吗?
    猜你喜欢
    • 2020-08-23
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 2019-05-19
    • 2019-03-07
    • 2020-01-11
    • 1970-01-01
    • 2019-08-07
    相关资源
    最近更新 更多