我碰到了什么题目?
不久之前我重构了一个陈旧的项目,总结了一些js方面的主意,不过关于一个前端项目而言不仅仅只由js构成的嘛,上学的时刻先生和我说HTML+CSS+JS对应的是页面的骨架、皮肤和肌肉。既然骨架我们有了,肌肉也聊完了,本日我们就来聊聊“皮肤”吧。
由于我重构的是一个react-native项目,所以我们先来讲说在react-native上是怎样写款式的吧,和传统的web不一样的是,在react-native上面是没有css代码,不过得益于Yoga,我们可以在客户端上像写css一样的去誊写我们的款式。我们来看看react-native文档上是怎样说的吧:
在React Native中,你并不须要进修什么迥殊的语法来定义款式。我们仍然是运用JavaScript来写款式。一切的中心组件都接收名为style的属性。这些款式名基本上是遵照了web上的CSS的定名,只是依据JS的语法请求运用了驼峰定名法,比方将background-color改成backgroundColor。
style属性可以是一个平常的JavaScript对象。这是最简朴的用法,因而在示例代码中很罕见。你还可以传入一个数组——在数组中位置居后的款式对象比居前的优先级更高,如许你可以间接完成款式的继续。
没错,你险些不须要什么本钱就可以依据写css一样的写法去写我们的rn款式,我们来看一下文档中的例子:
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, Text, View } from 'react-native';
export default class LotsOfStyles extends Component {
render() {
return (
<View>
<Text style={styles.red}>just red</Text>
<Text style={{
color: 'blue',
fontWeight: 'bold',
fontSize: 30,
}}>just bigblue</Text>
<Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text>
<Text style={[styles.red, styles.bigblue]}>red, then bigblue</Text>
</View>
);
}
}
const styles = StyleSheet.create({
bigblue: {
color: 'blue',
fontWeight: 'bold',
fontSize: 30,
},
red: {
color: 'red',
},
});
AppRegistry.registerComponent('LotsOfStyles', () => LotsOfStyles);
在上面的demo中,我们有两种体式格局去写我们的款式,它和我们在写css时刻碰到的外联式款式、内联式款式很相似,而项目中我们老是习气将款式和页面星散,然后把他们都放在别的一个style.js文件中。这是个异常不错的习气,然则也形成了一些搅扰。
面临一个页面,我该怎样去模块化它的款式呢?在之前的项目中虽然做到了款式和页面的星散,让页面“看起来”清洁了许多,然则在 style.js 文件中仍然是芜杂的代码,大批反复的变量、反复的内容、反复的声明。。。这个时刻又有同砚说了,我们可以把这些大众的变量、代码星散出来放到一个主题文件中呀,因而项目中除了各个页面的style.js以外又在全局涌现了一个theme.js文件,在这里人人兴奋的把诸如色彩、大小、规划等大众的代码放了进来。
这看似处置惩罚了style.js里反复冗余的代码,然则也会让我的import变得杂沓:
import { StyleSheet } from 'react-native';
import {
px,
COLOR_BG_RED,
COLOR_BG_GREEN,
STYLE_FR_VC_HSB,
STYLE_FR_VC_HC,
STYLE_FR_VC_HFS,
} from 'MyStyle';
export default StyleSheet.create({
// TODO
});
看到这里,我想你除了晓得我import进来了两个色彩以外,关于别的变量会一头雾水吧,除非你去MyStyle模块内里亲眼看一下才会晓得真正引入进来的是些什么了,假如这里的款式迥殊的多的话,除了再新建一个sytle.js以外,你就只能每次回到头部去看看自身引入了些什么。这是我不能忍耐的。。。
为你的款式分类
除了由于一次性引入太多的大众款式致使我要往返滑动以外,当我再去写一个新的styel.js文件时,复制这么多引入也是一件头疼的事变,那末我能不能每次只须要写一行import呢?假如我的款式都是按牢固划定规矩分类放好的是不是是每次就可以只import这几个类了呢?
常常写css的同砚肯定注重过款式的誊写递次,某一类的属性写在一同,虽然在web中,如许写是为了优化css引擎,然则这也表现出了款式是有肯定范例的,掌握色彩的、掌握边距的、掌握规划的,那末我们的大众变量是不是是也可以依据如许的划定规矩来声明呢?
import { color, size, layout } from 'MyStyle';
如许我们文件的头部是不是是就清晰多了呢?在写代码的时刻,也不须要再体贴我之前引入了些什么了,只需只需关注我们要写什么就好了:
export default StyleSheet.create({
lines: {
height: px(88),
backgroundColor: color.background,
borderLeftWidth: size.border,
borderRightWidth: size.border,
borderBottomWidth: size.border,
borderColor: color.border,
// 子元素横向分列,垂直居中,程度散布,中心用空格填满,最双方元素各自靠边
...layout.flex.vchbs,
},
});
在我的项目中默许边框的大小就是一个像素(1px),那末只需在最外层声清晰明了 size.border
的大小,背面写代码的时刻就可以畅行无阻的誊写下去了,实在我们已模块化了,只是我们还不够完全,不完全就代表着我们的代码不圆满,而且可复用性差,就如上面的demo,假如我们这里须要一个三面的边框,那末别的组件需不须要呢?假如须要的话是不是是也可以像我如许写呢?
固然是不可以!为何?由于我们是在复用这个边框,所以我们就不该再写一份如出一辙的代码了,而是应当写相似如许的:
export default StyleSheet.create({
lines: {
height: px(88),
backgroundColor: color.background,
// 一个边框粗细为1px的赤色边框
...layout.border
// 子元素横向分列,垂直居中,程度散布,中心用空格填满,最双方元素各自靠边
...layout.flex.vchbs,
},
});
如许我们的代码不仅少了许多,构造也清晰了,而且到时刻替代或许修正的时刻也轻易一些了,不过写成如许就完毕了嘛?固然不是了,我们如今有一个赤色的边框,所以我们在layout模块下新增了一个border属性,那末假如我们有一个蓝色的边框呢?一个绿色的粗边框呢?我们会一直往layout模块上新增属性嘛?那末了你晓得layout上面终究有若干属性嘛?那不就又回到一最先了嘛。。。
所以,我的发起是,处于根节点的模块最好掌握在3个摆布:
- color:用于寄存悉数项目的悉数色彩,这也代表着,在组件的style内部,我们不该当再显现的誊写诸如
backgroundColor: '#fff'
如许的代码了。 - size:用于寄存悉数项目的通用大小,比方说行高、间距、字体大小等大众的数值参数。
- layout:用于寄存悉数项目的大众规划,比方掌握规划的flex属性、通用的padding、margin、position定位。
那末第二级中的属性我也发起掌握在5个摆布:
- 色彩:边框色彩、背景色彩、字体色彩。。。
- 大小:边框大小、间距大小、字体大小。。。
- 规划:flex规划、position定位。。。
如许虽然增添了深度,然则分类清晰,构造明白,复用性也比较高。虽然能够会增添项目新建时的本钱(建立种种分类),然则会给后续的开辟、迁徙、重构、复用等带来极大的便利。但这就完毕了嘛?有的同砚和我说,我有许多的边框啊,我有许多款式要复用啊,到末了我的layout也会大到看不懂啊。。。另有的同砚说我没有那末多可复用的款式啊,那是不是是你总结的思绪就用不上了啊。固然不是咯,我们只完成了款式模块化的第一步(抽离款式),接下来最先第二步。
该怎样更便利的写款式?
如今许多web开辟者在誊写css的时刻已不再去写原生的css了吧,而是采纳比方scss、less如许的预编译言语去写款式了,那末这些预编译言语给我们带来了哪些轻易呢?我想大多半同砚第一时间都邑想到Mixin。
应用混合器,可以很轻易地在款式表的差别处所同享款式。假如你发明自身在不停地反复一段款式,那就应当把这段款式构形成优秀的混合器,尤其是这段款式自身就是一个逻辑单位,比方说是一组放在一同有意义的属性。
在react-native上面,我们的款式代码是js代码,所以很自然的就自带预编译,不须要别的分外的言语去处置惩罚它,要做的只是推断你的属性是不是须要一个Mixin。
推断一组属性是不是应当组合成一个混合器,一条履历轨则就是你可否为这个混合器想出一个好的名字。假如你能找到一个很好的短名字来形貌这些属性润饰的款式,比方rounded-cornersfancy-font或许no-bullets,那末每每可以构造一个适宜的混合器。假如你找不到,这时刻构造一个混合器能够并不适宜。
那末在js上面,我该怎样完成一个Mixin呢?太简朴了!我们只须要一个函数就可以了,没错,只须要一个返回对象的函数就可以做到如许的效果了,加上ES7的拓展运算符,我们就可以做到一个混合器的效果:
export default StyleSheet.create({
lines: {
height: px(88),
backgroundColor: color.background,
...layout.border(1px, '#fff')
},
});
常写react-native的同砚肯建都头疼过如许一个题目吧,就是我们并不能像写css款式一样在一行中把一切的属性都写完,在css中我们假如想要声明一个四周边框的大小,可以如许写:
.border {
border: 10px 5px 10px 5px;
}
那末在我们写款式的时刻是不是是也可以如许写:
export default StyleSheet.create({
lines: {
height: px(88),
backgroundColor: color.background,
...layout.border(10px, 5px, 10px, 5px),
},
});
我们可以经由过程函数的差别数目的参数来模仿传统css开辟的简写属性,许多时刻我们更习气在View上面去做款式的运算,应用react-native款式的掩盖数组去不停的掩盖之前的款式来到达运算的效果,这就致使View中除了须要盘算你的组件要不要展现、怎样展现以外,还要去盘算款式该怎样写,既然我们要做款式和页面的星散,那就应当做完全一些,将款式的盘算也放在style.js中。
总结
末了总结一下我们所做的:
- 星散款式和页面
- 提取项目级的大众属性
- 归类提取的大众款式
- 经由过程混合器去制造模板款式
我发起不管你的项目多大,代码若干,前三步都应当是一个必备的环节,能够你的项目不庞杂,临时用不到第四点,但前三条不管怎样都应当尽早的去完美,这不仅仅能协助你完成后续的迭代,也能在你的脑中保留出一个关于项目完全构造的印象,要晓得款式是寄生于页面的,清晰了款式,那末页面怎样你也若干会烂熟于心了。而比拟于经由过程梳理js的逻辑去相识悉数项目,我想经由过程页面或许会更快吧,这对方才接办项目的新同砚来讲,是异常和睦的。
末了的末了
平常到这里,就该放上自身开源的项目地点或许安利一波作者写的库了,不过和上一篇一样,这里我们只议论思绪,表述主意,而详细的实践和代码照样要靠我们自身在项目中不停的总结和积聚~
我置信许多同砚关于我提到的前三点都邑很快的明白,而关于第四点能够就有些懵了,该怎样去明白这个混合器呢?我该怎样用js去完成一个呢?下面我就用一段代码来举个例子,该怎样完成一个Mixin:
const layout = {
// 这里的形参递次遵照css中的 “上、右、下、左”
margin(...arg) {
let margin = {};
switch (arg.length) {
case 1:
margin = {
marginTop: arg[0],
marginRight: arg[0],
marginBottom: arg[0],
marginLeft: arg[0],
};
break;
case 2:
margin = {
marginVertical: arg[0],
marginHorizontal: arg[1],
};
break;
case 3:
margin = {
marginTop: arg[0],
marginHorizontal: arg[1],
marginBottom: arg[2],
};
break;
case 4:
margin = {
marginTop: arg[0],
marginRight: arg[1],
marginBottom: arg[2],
marginLeft: arg[3],
};
break;
default:
break;
}
return margin;
},
};
这是一个最浅易的Mixin,你可以依据你的需求去写更多如许的Mixin,实在我个人以为在项目一最先的时刻是不肯定须要这个的,这个存在的意义是关于庞杂款式誊写的,更多的情况下,你的项目只需做到了前三点,在款式这一块就已异常的整齐、完美了,多半情况下你不须要Mixin就可以构造好你的代码。
好了,以上就是此次我想和人人聊的关于react-native中款式的话题了,我们下次见~