2016-01-13 3 views
9

私はJavaScriptでデコレータを読んできました。私は基本的な前提を得ていると思います。ES7のクラスデコレータ

デコレータは関数で、デコレートすべきものを1つまたは複数のパラメータとして受け取り、結果を返します。

しかし、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 { } 

この例では、ファクトリ関数は元のクラスをラップするコンストラクタ関数を返します。この関数は元のクラスの代わりにオブジェクトを作成するために使用されます。あなたのケースでは、CSSを挿入/削除するためにイベント(componentWillMountcomponentWillUnmount)を処理し、元のコンポーネントをその小道具でレンダリングします。

これはデコレータによってオーバーライド本来のコンストラクタ関数である方法を示す非常に単純な例です:

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 
関連する問題