我想为React Native编写类似SCSS的东西:它将解析你的组件jsx和类似SCSS的特殊样式,并返回一个带有重写样式和jsx的常用RN组件。
让我们说我们有这个反应代码:
class MyClass extends Component {
render() {
return (
<View style={styles.container}>
<Text>I remember syrup sandwiches</Text>
</View>
);
}
}
我也有SCSS-ish样式,其中父容器中的每个Text组件与容器“class”将具有我们提供的相同道具。
const styles = StyleSheet.create(
toRNStyles({
container: {
Text: { color: 'red' },
},
})
);
最后我们需要这样的输出:
...
<View style={styles.container}>
<Text style={styles._Text_container}>
I remember syrup sandwiches
</Text>
</View>
...
那么如何才能从类外部获取从render方法返回的jsx?
答案 0 :(得分:2)
你可能会为babel编写一个插件,因为react-native使用它来将JSX转换为普通的javascript。 看看这些包:
答案 1 :(得分:1)
似乎没有一种标准的方法可以做到这一点。但是,您可以导入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>
答案 2 :(得分:1)
我认为解析返回的元素是错误的方法。一个挑战是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>
);
};
&#13;
<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>
&#13;