ES7中的类装饰器

Som*_*Guy 11 decorator reactjs ecmascript-7

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

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

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

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;
Run Code Online (Sandbox Code Playgroud)

用例就是

import s from './MyComponentStyle.scss';

@withStyles(s)
class MyComponent extends Component {

}
Run Code Online (Sandbox Code Playgroud)

这是如何运作的?

mad*_*ox2 14

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

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

@myDecorator('myValue')
class MyClass { }
Run Code Online (Sandbox Code Playgroud)

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