Class ES7 中的装饰器

Class decorators in ES7

我一直在阅读 JavaScript 中的装饰器,我认为我已经掌握了基本前提。

装饰器是函数,它们接收一个或多个参数作为它们应该装饰的内容,以及 return 结果。

但是我在 React Boiler Plate 项目中遇到了一个 @withStyles 修饰的实现,我不明白它是如何工作的。

import React, { Component, PropTypes } from 'react';

function withStyles(...styles) {
  return (BaseComponent) => class StyledComponent extends Component {
    static contextTypes = {
      insertCss: PropTypes.func.isRequired,
    };

    componentWillMount() {
      this.removeCss = this.context.insertCss.apply(undefined, styles);
    }

    componentWillUnmount() {
      this.removeCss();
    }

    render() {
      return <BaseComponent {...this.props} />;
    }
  };
}

export default withStyles;

一个用例是

import s from './MyComponentStyle.scss';

@withStyles(s)
class MyComponent extends Component {

}

这是如何工作的?

Class 装饰器可以用作工厂函数。例如:

function myDecorator(value) {
   return function(target) {
      target.myProperty = value;
   }
}

@myDecorator('myValue')
class MyClass { }

在您的示例中,工厂函数 returns 构造函数包装了原始 class。该函数用于创建对象而不是原来的class。在您的情况下,它处理事件(componentWillMountcomponentWillUnmount)以便 insert/remove css 并使用其道具呈现原始组件。

这是一个非常简单的示例,演示了装饰器如何覆盖原始构造函数:

function myDecorator(name) {
   return (target) => class Wrapper {
       sayHello() {
           const targetObject = new target();
           console.log(`wrapper ${name} says hello`);
           targetObject.sayHello();
       }
       wrapperMethod() {
           console.log('calling wrapper function');
       }
   };
}

@myDecorator('Jack')
class MyClass {
    sayHello() {
        console.log('original says hello');
    }
    myMethod() {
       console.log('calling original function');
    }
}

var obj = new MyClass();

obj.sayHello();
//wrapper Jack says hello
//original says hello

obj.wrapperMethod();
//calling wrapper function

obj.myMethod();
//TypeError: obj.myMethod is not a function