ES7中的类装饰器

时间:2016-01-13 12:31:24

标签: reactjs decorator ecmascript-7

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

装饰器是函数,它们接收它们应该装饰的一个或多个参数,并返回结果。

但是我在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 {

}

这是如何运作的?

1 个答案:

答案 0 :(得分:14)

类装饰器可用作工厂功能。例如:

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

@myDecorator('myValue')
class MyClass { }

在您的示例中,工厂函数返回包装原始类的构造函数。此函数用于创建对象而不是原始类。在您的情况下,它处理事件(componentWillMountcomponentWillUnmount)以插入/删除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