问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何在React Native中设计主题机制

发布网友 发布时间:2022-05-10 22:11

我来回答

1个回答

热心网友 时间:2022-04-20 07:46

1:样式变量
web上,我们从css到scss/sass/less,然后我们才有变量可以用。然而在RN里,我们的样式本来就是JS化的,我们可以自由的使用JavaScript的变量以及其它特性来完成样式化:
// theme.js
var globalTextColor = '#000000',
mole.exports = {
backgroundColor: '#FFFFFF',
title: {
size: 32,
color: globalTextColor
},
content: {
size: 16,
color: globalTextColor
}
};
// styles.js
var React = require("react-native");
var {StyleSheet} = React;
var theme = require("./theme")
mole.exports = StyleSheet.create({
titleText : {
fontWeight: 'bold',
...theme.title
},
container1: {
background: theme.backgroundColor
},
container2: {
background: theme.backgroundColor
},
content: {
...theme.content
}
})
这样做,我们已经可以把一些需要经常修改的样式(如颜色、字体、尺寸等)和一些结构性的样式(譬如flex、position)等拆分开来,并且可以定义一些可以影响到多个样式的变量(如上文的globalTextColor)。对于日常的样式迭代,这已经可以满足一部分需求了,我们还可以根据自己的需要进行一些定制的预计算。而且这应当是最易理解的方式。不过这并不能实现用户切换主题的需求。
2:在组件上使用多个样式
类似ReactJS中我们使用classnames插件,ReactNative天然就支持使用数组提供多个样式的方式:
<View style={[styles.base, styles.background]} />
所以我们也可以在组件里分开引用默认样式和主题化的样式:注意这里theme返回的不是上文中的一个纯对象,而是另一个stylesheet
var React = require('React');
var styles = require('./styles');
var theme = require('../theme');
class Article extends React.Component {
render(){
return (
<View style={[style.container, theme.container]}>
<Text style={[styles.title, theme.title]}>
{this.props.title}
</Text>
<Text style={[styles.content, theme.content]}>
{this.props.content}
</Text>
</View>
);
}
};
3. 附加样式
首先,当我们实现一个通用组件的时候,应当让它可以在默认的style的基础上允许附加style(也即:允许外部进一步指定style属性):
var styleSheet = StyleSheet.create({
container: {
flex: 1
}
})
class Article extends React.Component{
render(){
var {
title, content,
style, titleStyle, contentStyle,
...others
} = this.props;
if (Array.isArray(style)){
style = [styleSheet.container, ...style];
} else {
style = [styleSheet.container, style];
}
//或者合并成这样一句: style=[styleSheet.container].concat(style);
return (
<View style={style} {...others}>
<Title style={titleStyle}>
{title}
</Title>
<Content style={contentStyle}>
{content}
</Content>
</View>
)
}
}
// Now you can use in this way:
<Article style={theme.article} title="Title" content="Foo" />
如果所有组件代码都支持附加样式,我们就比较方便通过props来传递额外的样式,这样,我们就可以引入一个新的黑科技:
4. 叠加默认属性黑魔法: 使用增强组件(EnhancedComponent)模式
如果我们可以给一个组件叠加一个默认样式,就可以让我们的许多工作简单的多(譬如上文的Title和Content,可以在Text的基础上直接叠加默认属性和样式得到)
export var Title = enhanceComponent(Text, {
style: styleSheet
});
export var Content = enhanceComponent(Text, {
style: {
fontSize: 16,
}
});
实际上,这个enhanceComponent很容易实现:
function enhanceComponent(Component, props){
var {style, ...others} = props;
return class extends React.Component {
render(){
var newProps = {...props};
for (var k : this.props){
if (/[sS]tyle$/.test(k) && newProps[k]) {
// merge style
newProps[k] = [].concat(newProps[k], this.props[k]);
} else if (k != 'children') {
// assign normal prop.
newProps[k] = this.props[k];
}
}
return (
<Component {...newProps}>
{this.props.children}
</Component>
)
}
};
}
所有名字以style或Style结尾的的属性被当做样式处理(处理类似titleStyle的情况)
5. 主题化组件
在3和4的基础上,结合ES6的一部分语法,我们应当可以以一种反向的方法来提供主题:提供一套主题化的组件。在此之前,我们的Article还需要做一些修改来适应:
var styleSheet = StyleSheet.create({
container: {
flex: 1
}
})
class Article extends React.Component{
render(){
var {
title, content, style,
createTitle, createContent
...others
} = this.props;
if (Array.isArray(style)){
style = [styleSheet.container, ...style];
} else {
style = [styleSheet.container, style];
}
//或者合并成这样一句: style=[styleSheet.container].concat(style);
return (
<View style={style} {...others}>
{createTitle ? createTitle(title) : <Title>
{title}
</Title>}
{createContent ? createContent(content) : <Title>
{content}
</Title>}
</View>
)
}
}
// Now you can use in this way:
<Article title="Title" content="Foo" createTitle={title=><Title style={theme.title}>{title}</Title>}/>
上面这个修改增加了createTitle和createContent函数,而取消了titleStyle和contentStyle(不够通用),实际上这也接近大部分内置库或第三方库所提供自定义化组件的方式(譬如为ListView提供ScrollBar)。
然后,我们可以编写这样一个themedComponents.js
// themedComponents.js
var themes = require("./themes");
import Article, {Title, Content} from './components/Article';
export var ThemedTitle = enhanceComponent(Title, {
style: themes.title
});
export var ThemedContent = enhanceComponent(Text, {
style: themes.content
});
export var ThemedArticle = enhanceComponent(Article, {
style: themes.article,
createTitle: title=>(<ThemedTitle>title</ThemedTitle>),
createContent: content=>(<ThemedContent>title</ThemedContent>),
});
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
arrive in和arrive at 有什么区别? 磁力泵为什么可空转? 为什么不让衬氟塑料磁力泵空转?怎样提升设备稳定性? 工业软管泵 塑料磁力泵为什么不能空转 求推荐男主和女配在一起的小说? 《红衣天下》txt全集下载 检测公司检测哪些 检测公司是怎么样的 检测公司属于什么企业 求:外研社新标准初三下册英语课文听力 (Module1的主题为:Travel) 求初一下学期 Module7--Module12的主题作文、谢、 哈尔滨有几家小米的售后服务网点? 申报高新技术企业认定有什么好处?能享受什么优惠*啊?哪里有申报高新技术企业认定的详细介绍? 高新技术企业认证的代理公司,哪些好呀? 高新技术企业认证哪家好,项目申报创新基金项目申报 深圳地铁站机场北和机场站有什么区别 车载凯立德导航怎么升级,步骤? 深圳地铁11号线坐飞机是在机场还是机场北? 深圳新机场大概多少平方米?多少亩地? 深圳地铁11号线机场北站t4航站楼离万科金色领域有多远 穗莞深城际深圳机场站与深圳机场北的区别? 宝安机场站和新航站楼哪个站离轻轨最近? 深圳机场有块铁口吗? 深圳机场北站怎么是工地? 梁品在商标31类是什么意思? 安卓手机用什么软件看word文档反应最快? 东北电力大学成人自考,能靠服装专业么? 沈阳工业大学和东北电力大学哪个厉害 2011东北电力大学*高考高起本录取结果什么时候下来?我考了460多分,能考上么?我是黑龙江考生 单招考试计算机软件行业相关主题都有什么 foobar2000如何使用别人分享的DUI主题 Android studio 布局主题有问题 求助 如何替换Drupal主题的幻灯片? 高二英语周报book5module2 普通26寸自行车轴承型号 普通26寸自行车前后老轴可换轴承吗? 26寸的传动轴自行车的中轴齿轮哪里有买?请教高人 普通捷安特26寸女式自行车中轴坏想换一体中轴不知多长请高手指教 自行车26寸三十刀是什么意思 普通26寸自行车前后老轴可换轴承吗 裁床弹性布人工拉布技巧 电动缝纫机缝弹力布小窍门 这个面料怎么缝纫啊? 贾乃亮直播2.4亿破纪录,下跪痛哭,比面子更重要的是什么? 景甜说看刘宇宁直播路转粉了,如何看待刘宇宁的职业生涯? 淘宝店被扣分了如何申诉 电子商务的安全技术有哪些? 被处罚扣分怎么申诉 33岁丫蛋二婚后露面疑怀孕,直播惨淡公司艰难,离开春晚她咋销声匿迹?