2016-01-13 98 views
9

我一直在阅读JavaScript中的装饰器,并认为我得到的基本前提。ES7中的类装饰器

装饰器是函数,他们收到一个或几个参数,他们应该装饰,并返回结果。

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

} 

这是如何工作的?

回答

13

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

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

@myDecorator('myValue') 
class MyClass { } 

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

这是非常简单的例子演示了如何在原有的构造函数由装饰overrided