2017-06-27 37 views
0

我想爲React Native寫一些類似SCSS的東西:它會解析你的組件jsx和特殊的類似SCSS的樣式,並返回一個通用的RN組件和重做樣式和jsx。如何從類渲染方法中提取JSX?

比方說我們有這個反應代碼:

class MyClass extends Component { 
    render() { 
    return (
     <View style={styles.container}> 
     <Text>I remember syrup sandwiches</Text> 
     </View> 
    ); 
    } 
} 

我也有SCSS十歲上下的風格,其中一個容器「類」父內的每個文本組件將有我們提供的相同的道具。

const styles = StyleSheet.create(
    toRNStyles({ 
    container: { 
     Text: { color: 'red' }, 
    }, 
    }) 
); 

最終我們需要的是這樣的輸出:

... 
<View style={styles.container}> 
    <Text style={styles._Text_container}> 
    I remember syrup sandwiches 
    </Text> 
</View> 
... 

所以,我怎麼能得到這與渲染方法返回從類以外的JSX?

+0

的目的是什麼,你所需要的輸出?如果您需要在運行時進行調整,則可以使用'render()'作爲@yoda建議的值,或者使用高階分量包裝組件。此外,輸出不是JSX(這是使用組件的語法),而是一個React元素(它是描述組件實例的對象) – ryanjduffy

+0

爲什麼要這樣做?提供一些背景。可能這不是你想要做的,來解決你的問題。 – trixn

+2

[XY問題](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) –

回答

0

您可能會爲babel編寫一個插件,因爲react-native會使用它將JSX轉換爲純javascript。 看一看在這些軟件包:

  • 巴貝爾輔助建設者 - 反應 - JSX
  • 巴貝爾,插件,語法JSX
  • 巴貝爾 - 插件 - 轉換 - 反應 - JSX
  • 巴貝爾-plugin變換反應的-JSX源
  • JSX-AST-utils的
0

似乎沒有被這樣做的標準方式。但是,您可以導入ReactDOMServer並使用它的renderToStaticMarkup函數。

像這樣:

class MyApp extends React.Component { 
 
    render() { 
 
    var myTestComponent = <Test>bar</Test>; 
 
    console.dir(ReactDOMServer.renderToStaticMarkup(myTestComponent)); 
 
    
 
    return myTestComponent; 
 
    } 
 
} 
 

 
const Test = (props) => { 
 
    return (
 
    <div> 
 
     <p>foo</p> 
 
     <span>{props.children}</span> 
 
    </div> 
 
); 
 
} 
 

 
ReactDOM.render(<MyApp />, document.getElementById("myApp"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom-server.js"></script> 
 
<div id="myApp"></div>

0

我想解析返回的元素是錯誤的做法。一個挑戰將是style的值將是一個對象(styles.container ===樣式鍵/值的散列),而您需要可以映射到該對象的鍵。

我認爲最可重用的方法是利用React上下文(我假設RN支持!)來構建一個styleName,隨着組件樹的發展,它可以得到增強。

這裏有一個初始方法,它提出了一些假設(例如,每個組件都會有styleName作爲道具提供;您可能希望在設計時提供它,而不是運行時)。簡而言之,你用本HOC包裝你想參與的每個組件,並提供styleName作爲每個組件的道具。這些styleName值連接在一起以產生映射到樣式的上下文化名稱。

該示例產生:

<div style="background-color: green; color: red;"> 
    <div style="color: blue;">Some Text</div> 
</div> 

const CascadingStyle = (styles, Wrapped) => class extends React.Component { 
 
    static displayName = 'CascadingStyle'; 
 
    
 
    static contextTypes = { 
 
    styleName: React.PropTypes.string 
 
    } 
 
    
 
    static childContextTypes = { 
 
    styleName: React.PropTypes.string 
 
    } 
 
    
 
    // pass the current styleName down the component tree 
 
    // to other instances of CascadingStyle 
 
    getChildContext() { 
 
    return { 
 
     styleName: this.getStyleName() 
 
    }; 
 
    } 
 

 
    // generate the current style name by either using the 
 
    // value from context, joining the context value with 
 
    // the current value, or using the current value (in 
 
    // that order). 
 
    getStyleName() { 
 
    const {styleName: contextStyleName} = this.context; 
 
    const {styleName: propsStyleName} = this.props; 
 
    let styleName = contextStyleName; 
 

 
    if (propsStyleName && contextStyleName) { 
 
     styleName = `${contextStyleName}_${propsStyleName}`; 
 
    } else if (propsStyleName) { 
 
     styleName = propsStyleName; 
 
    } 
 

 
    return styleName; 
 
    } 
 
    
 
    // if the component has styleName, find that style object and merge it with other run-time styles 
 
    getStyle() { 
 
    if (this.props.styleName) { 
 
     return Object.assign({}, styles[this.getStyleName()], this.props.styles); 
 
    } 
 

 
    return this.props.styles; 
 
    } 
 
    
 
    render() { 
 
    return (
 
     <Wrapped {...this.props} style={this.getStyle()} /> 
 
    ); 
 
    } 
 
}; 
 

 
const myStyles = { 
 
    container: {backgroundColor: 'green', color: 'red'}, 
 
    container_text: {color: 'blue'} 
 
}; 
 

 
const Container = CascadingStyle(myStyles, (props) => { 
 
    return (
 
    <div {...props} /> 
 
); 
 
}); 
 

 
const Text = CascadingStyle(myStyles, (props) => { 
 
    return (
 
    <div {...props} /> 
 
); 
 
}); 
 

 
const Component =() => { 
 
    return (
 
    <Container styleName="container"> 
 
     <Text styleName="text">Some Text</Text> 
 
    </Container> 
 
); 
 
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>