javascript - 带有 React 组件的装饰器

标签 javascript reactjs babeljs ecmascript-next

我对能够使用 @myDecorator 语法(使用 babel)感到非常兴奋。我正在尝试装饰生命周期函数之一,特别是 componentWillMount,并检查装饰器中组件的 propscontext。但是,我似乎无法访问 propscontext。我不确定这是否是一种反模式,或者我只是在做这个错误。

小例子:

// TestComponent.jsx
import checkProps from 'checkProps.js';

class TestComponent extends React.Component {
    @checkProps
    componentWillMount() {
        // Do something.
    }

    render() {
       return <div>My Component</div>
    } 
}

// checkProps.js
export function checkProps(target) {
    console.log(target.props);
}

我也尝试过装饰器的箭头函数并检查 this,但我认为装饰器不会以这种方式组合东西。

我也尝试过让我的装饰器成为工厂并传入 this.propsthis.context 但是 this 在装饰 a 时未定义组件生命周期函数。

最佳答案

ES7 ECMAScript 装饰器有 the same API as Object.defineProperty(target, name, descriptor)所以 target 参数是应用装饰器时的类,而不是 React 调用它时的类。要影响装饰器在运行时所做的事情,您必须修改 descriptor.value,即被装饰的实际函数:

export function checkProps(target, name, descriptor) {
    // Save the original method, it'd be a good idea
    // to check that it really is a function
    const decoratee = descriptor.value;

    // Modify the descriptor to return our decorator
    // function instead of the original
    descriptor.value = function decorated(...args) {
        // Do something before ...
        console.log('before: ' + name, this.props, args);

        // Calling the decorated method on this object
        // with some arguments that could have been 
        // augmented by this decorator
        decoratee.apply(this, args);

        // Do something after ...
        console.log('after: ' + name);
    };
} 

// Or if you wanted to use a factory function to supply some configuration
// to the decorator you can do it this way

export function checkProps(config) {
    return function configurableCheckProps(target, name, descriptor) {
        // Save the original method, it'd be a good idea
        // to check that it really is a function
        const decoratee = descriptor.value;

        if (config.someOption) {
            // Do something based on the config
        }

        // Modify the descriptor to return our decorator
        // function instead of the original
        descriptor.value = function decorated(...args) {
            // Do something before ...
            console.log('before: ' + name, this.props, args);

            if (config.someOption) {
                // Do something based on the config
            }

            // Calling the decorated method on this object
            // with some arguments that could have been 
            // augmented by this decorator
            decoratee.apply(this, args);

            // Do something after ...
            console.log('after: ' + name);
        };
    };
} 

这是 an example that also modifies the behavior of a method这更彻底地证明了这一点。

希望这对您有所帮助。编码愉快!

编辑:正如评论者所指出的,装饰器不是 ES7 的一部分,但截至 2016 年 3 月the proposal is still in Stage 1 , 我的坏

EDIT2:截至 2018 年 6 月,提案在 the proposal is still in Stage 2 中, 我们越来越近了

关于javascript - 带有 React 组件的装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36286384/

相关文章:

javascript - 无法读取未定义的属性 'setState'

javascript - 将 angularjs 模块导出为 es6 模块

php - KCFinder - browse.php 下载而不是显示页面

JavaScript 函数

javascript - React + immutableJS 在旧浏览器中呈现一些奇怪的输出

javascript - 如何在 JavaScript 文件中启用 Emmet 的制表键处理程序(HTML 快捷方式)?

reactjs - 运行玩笑测试时,覆盖失败并出现意外 token

javascript - Angularjs 和谷歌地图,单击时将范围变量设置为 map 中的值

javascript - Angular Service Worker,缓存离线应用程序的api调用

javascript - 支持 Route hoc 中 React Router 的渲染属性