2016-01-13 5 views
9

Ich habe auf Dekoratoren in JavaScript gelesen und denke, dass ich die Grundvoraussetzung bekomme.Klasse Dekorateure in ES7

Dekoratoren sind Funktionen, sie erhalten als ein oder mehrere Parameter, was sie dekorieren sollen, und geben das Ergebnis zurück.

Aber ich kam über eine @withStyles dekoriert Umsetzung in einem React Boiler Plate-Projekt, das ich nicht verstehe, wie funktioniert.

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; 

A würde Anwendungsfall

import s from './MyComponentStyle.scss'; 

@withStyles(s) 
class MyComponent extends Component { 

} 

sein Wie funktionierts?

Antwort

13

Class Decorators können als Werksfunktionen verwendet werden. Beispiel:

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

@myDecorator('myValue') 
class MyClass { } 

In Ihrem Beispiel gibt die Factory-Funktion die Konstruktorfunktion zurück, die die ursprüngliche Klasse umschließt. Diese Funktion wird verwendet, um ein Objekt anstelle der ursprünglichen Klasse zu erstellen. In Ihrem Fall behandelt es Ereignisse (componentWillMount,), um CSS einzufügen/zu entfernen, und rendert die ursprüngliche Komponente mit ihren Requisiten.

Diese sehr einfaches Beispiel zeigt, wie die ursprüngliche Konstruktor Funktion von Dekorateur overrided:

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