
版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。
PS:轉(zhuǎn)載請(qǐng)注明出處
作者: TigerChain
地址: http://www.itdecent.cn/p/dd2a5b1b95c5
本文出自 TigerChain 簡(jiǎn)書(shū) ReactNative 系列
教程簡(jiǎn)介
- 1、閱讀對(duì)象
本篇教程適合新手閱讀,老手直接略過(guò)
-
2、教程難度
初級(jí)
3、Demo 地址:https://github.com/tigerchain/rn-lesson/tree/master/lesson01/02、stylecomponents/styleComponent
我們都知道在 RN 中使用的的內(nèi)聯(lián)樣式,是通過(guò) StyleSheet 組件創(chuàng)建出來(lái)的樣式「當(dāng)然也可以使用 const style={} 來(lái)定義」
對(duì)于 web 開(kāi)發(fā)者來(lái)說(shuō),特別是使用 css 樣式的人來(lái)說(shuō)寫(xiě)樣式的時(shí)候總是不自覺(jué)的要加一個(gè) - ,那么你也可以使用樣式組件--styled-components ,這們來(lái)重點(diǎn)介紹一下 styled-components
一、 什么是 styled-components
熟悉前端的童鞋都知道,html 中引入 css 有三種方式
- 嵌入式
<head>
<style type="text/css">
h3{color:red}
span{color:blue}
</style>
<head>
- 內(nèi)聯(lián)式
<p style="color:#FFEECC;font-weight:bold;">內(nèi)聯(lián)樣式</p>
- 外部引用入,有 link import 等
這里說(shuō)一下 link
<link rel="stylesheet" type="text/css" href="theme.css" />
<html>
指令語(yǔ)句
</html>
在 RN 中使用的也是內(nèi)聯(lián)樣式,那有沒(méi)有一個(gè)既有 web 開(kāi)發(fā)中 css 書(shū)寫(xiě)特性,也能把 React 組件化思想結(jié)合在一起「有樣式的組件」組件呢?styled-components 就能滿足我們的需求
styled-components 則是一個(gè)把組件和 style 聯(lián)系在一起的一個(gè)組件庫(kù),為 React 和 ReactNative 提供一個(gè)干凈,易于使用的界面,說(shuō)白了就是在 js 上寫(xiě) css ,移除了組件和樣式的映射關(guān)系。是 style 的另一種思想,簡(jiǎn)單的舉個(gè)例子來(lái)直觀的感受一下吧,如下:定義了一個(gè)帶有樣式的 Button ,怎么樣帥吧
const Button = styled.Button`
color:red;
font-size:16;
margin:1;
padding:0.5,1;
...
`
PS:其中 styled.Button 是一個(gè)標(biāo)簽?zāi)0婧瘮?shù),緊跟在后面的 `...` 是一個(gè)模版字符串,模版函數(shù)和模版字符串都是 ES6 的語(yǔ)法,如果不清楚的可以查看 ES6 相關(guān)知識(shí)
二、styled-components 的使用
這里我們以 RN 舉例子來(lái)說(shuō)明,React 使用套路是一樣的
1、在指定目錄下創(chuàng)建一個(gè) RN 項(xiàng)目
react-native init styleComponent
2、安裝 styled-components
npm install --save styled-components 或 yarn add styled-components
我們看一下 package.json 中已經(jīng)成功添加了 styled-components 并且版本是 2.2.0

3、新建 app 目錄,并且新建 main.js,并將 main.js 添加到時(shí) index.android.js 和 index.ios.js 中
修改 index.android.js 和 index.ios.js 核心代碼

4、在 app 目錄中新建 inlineStyle.js 和 StyleComponent.js 文件
- 我們使用傳統(tǒng)的 rn 樣式方法來(lái)創(chuàng)建一個(gè)背景為紅色,并且字為紅色的按鈕,如下:

# inlineStyle.js
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
} from 'react-native';
/**
* @author TigerChain
* 普通的內(nèi)聯(lián)樣式的組件
* @type {Object}
*/
export default class InlineStyle extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.inlineText}>I'm the InlineStyle button</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor:'red',
height:40,
justifyContent:'center',
alignItems:'center'
},
inlineText:{
color:'yellow',
fontSize:18
}
});
- 2、定義 StyleComponent.js
# StyleComponent.js
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
} from 'react-native';
import styled from 'styled-components/native'
/**
* @author TigerChain
* 使用 styled-components 聲明組件
* @type {Object}
*/
const StyledView = styled.View`
background-color: red;
height: 40;
justify-content:center;
align-items: center;
`
const StyleText = styled.Text`
color: yellow;
font-size: 18;
`
const StyleComponent = (props)=>(
<StyledView>
<StyleText>styled-components 聲明的 Button</StyleText>
</StyledView >
)
module.exports = StyleComponent
style-components 格式
我們可以看到使用 styled-components 來(lái)編寫(xiě)樣式組件的格式是
const CustomView = styled.XXX`
樣式
`
其中 XXX 就是 RN 中的組件,比如 Text,View,Button 等
PS:使用 styled-components 要先引入這個(gè)庫(kù)
import styled from 'styled-components/native' 我們來(lái)對(duì)比一下兩種方式吧

把兩個(gè)組件組合到 main.js 中

兩種方式寫(xiě)的生成的一個(gè)相同的組件最后運(yùn)行效果如下:

經(jīng)過(guò)以上代碼,我們簡(jiǎn)單的了解了一下 styled-components 是個(gè)什么鳥(niǎo),并且如何使用,下面我們來(lái)說(shuō)一些高級(jí)用法吧
三、styled-components 的高級(jí)用法
1、傳遞屬性「定制組件」
- 1、我們先看一個(gè) React 的例子吧「注意這里說(shuō)的是 React 」
假如我們想要定義按鈕的樣式,分別為大、小,我們會(huì)這樣做,新建一個(gè) css 文件
css 文件
.button{
background:red;
border-radius: 8px;
color: yellow;
}
.large{
height:60px;
width:180px;
}
.small{
height:40px;
width:100px;
}
js 文件
class CustomButton extends React.Component {
render() {
return (
<div>
<button className="small">按鈕</button>
<button className="large">按鈕</button>
</div>
)
}
}
我們想在 rn 使用 styled-components 實(shí)現(xiàn)以上類(lèi)似的功能如何辦呢?傳遞 props 就派上用場(chǎng)了,廢話不多說(shuō),直接上代碼
- 2、使用 styled-components 完成上面的按鈕組件
修改 styleComponent.js,并聲明一個(gè)可指定大小的按鈕組件
const CustomButton = styled.View`
background-color: ${props => props.red?'red':blue};
border-radius: 8;
margin-top: 10;
justify-content: center;
align-items: center;
height: ${props => props.small?40:60};
width:${props => props.small?100:180}
`
然后引用即可
<CustomButton small red>
<StyleText >TigerChain</StyleText>
</CustomButton>

2、對(duì)任何組件進(jìn)行樣式化
我們項(xiàng)目中有時(shí)會(huì)用三方組件,我們想必變?nèi)浇M件的樣式,styles-components 也是完美支持的,看核心代碼
// 定義可被任意樣式的組件 熟悉 props 的都知道這里的 children是啥意思,style 就不用說(shuō)了
const CustomText = ({style,children}) =>(
//這里還可以是任意三方組件
<Text style={style}>
{children}
</Text>
)
// 給上面的組件添加樣式
const StyledText2 = styled(CustomText)`
color: palevioletred;
font-weight: bold;
font-size: 18;
`;
使用方式
<CustomText>TigerChain</CustomText>
<StyledText2>給 TigerChain 添加樣式</StyledText2>
運(yùn)行查看結(jié)果:

大體一個(gè)過(guò)程如下:

3、樣式繼承
- 格式:
const CustomComponent = styled.Component`
樣式
`
const MyComponent = CustomComponent.extend`
擴(kuò)展樣式或重寫(xiě)樣式
...
`
- 在 styleComponent.js 中添加自定義樣式擴(kuò)展組件
//定義可繼承的組件
const MyCusTomText = styled.Text`
color: red;
margin-top: 8;
`
//擴(kuò)展組件
const ExtendText = MyCusTomText.extend`
font-size:25;
font-weight:bold;
`
- 使用
<MyCusTomText>自定義文本</MyCusTomText>
<ExtendText>擴(kuò)展文本</ExtendText>
- 運(yùn)行查看結(jié)果

4、附加 props 使用 .attrs 構(gòu)造函數(shù)
在 .attrs 構(gòu)造函數(shù)中,我們可以聲明靜態(tài) props ,動(dòng)態(tài) props ,目的是為了避免傳遞不必要的屬性
- 格式:
const MyView = styled.View.attrs({
...
xxx:props => props.yyy
...
})`
xxx:${props => props.xxx}
`
- 以上格式看起來(lái)比較模糊,我們通過(guò)代碼來(lái)感受一下
// 使用 .atrr 來(lái)添加額外的 props
const AtrrView = styled.View.attrs({
//聲明一些 props 屬性
height:props => props.height || 40,
background:props => props.bgcolor || 'red',
})`
border-radius:5;
height:${props => props.height}
background-color:${props => props.background}
justify-content:center;
align-items:center;
`
使用并查看結(jié)果
<AtrrView bgcolor='orange' height='80'>
<Text>
我是 .attrs 屬性
</Text>
</AtrrView>
結(jié)果如下:

過(guò)程分析

總結(jié):
經(jīng)過(guò)以上我們對(duì) styled-componets 有了一個(gè)大體的認(rèn)識(shí)和了解,styled-components 還支持動(dòng)畫(huà)等,具體可以去官網(wǎng)查看,總結(jié) styled-componentd 有以下特點(diǎn)
- 是 css in js 的一種實(shí)現(xiàn)方式
- 移除了樣式和組件的映射關(guān)系
- 使用組件看起來(lái)更清晰
- 使樣式組件和邏輯組件更好的區(qū)分開(kāi),使得兩種組件解耦
- 與傳統(tǒng)單一職責(zé)相比,styled-components 就相當(dāng)于富二代,與生俱來(lái)就可以寫(xiě)一個(gè) style 的組件「?jìng)鹘y(tǒng)的推崇 html css js 等都要分開(kāi)」
這個(gè)玩意開(kāi)始寫(xiě)的時(shí)候人很別扭「特別對(duì)于喜歡 js css html 分離的人」,但是寫(xiě)著寫(xiě)著就有一種巴黎歐萊雅的感覺(jué)---你值得擁有
三、性能對(duì)比
既然 styled-components 讓組件擁有完整的功能,并且是目前前端變化的趨勢(shì),那么我們到底該不該使用 styled-components 呢?說(shuō)到這里估計(jì)有人要罵筆者了「我靠,我都照著你說(shuō)的的代碼擼了一遍了,你居然這樣說(shuō)...」。我只想說(shuō)年輕人,稍安勿躁
一個(gè)組件不光是好用就是我們要選擇的理由,我們還要考慮性能、組件對(duì)包大小的影響,兼容性的影響等等,這里我們對(duì)比一下 styled-components 和傳統(tǒng)的 in-line css 的性能
開(kāi)始擼碼
在上面 demo 的基本上添加代碼,在這里我們要統(tǒng)計(jì)一代碼的執(zhí)行時(shí)間,所以安裝一個(gè)依賴(lài)庫(kù) react-native-console-time-polyfill
yarn add react-native-console-time-polyfill
- 1、在 app 目錄中新建 StyledComponentsPerformance.js
/* @flow weak */
import React, { Component} from 'react';
import {
View,
Text,
StyleSheet,
ListView
} from 'react-native';
import styled from 'styled-components/native'
import 'react-native-console-time-polyfill'
import data from './Data'
const ListItemView = styled.View`
padding-top: 5;
padding-bottom: 5;
border-bottom-width: 1;
border-bottom-color: red;
`;
const ListItemText = styled.Text`
color:red;
font-size: 18;
`;
const ScrollViewStyled = styled.ScrollView`
`;
const ListViewStyled = styled.ListView`
`;
/**
* 樣式組件性能測(cè)試
* @type {ListView}
*/
export default class StyleComponentPerformance extends Component {
constructor(props) {
super(props);
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
this.state = {
dataSource: ds.cloneWithRows(data),
};
}
componentWillMount() {
console.log(`ListView - 渲染 ${data.length} 個(gè)組件`);
console.time('styled-components');
}
componentDidMount() {
console.timeEnd('styled-components');
}
renderRow = (row) =>(
<ListItemView><ListItemText>{row.name}</ListItemText></ListItemView>
)
renderListView() {
return (
<ListViewStyled
dataSource={this.state.dataSource}
renderRow={this.renderRow}
enableEmptySections={true}
/>
);
}
renderScrollView() {
return (
<ScrollViewStyled>
{data.map((row, index) => <ListItemView key={index}><ListItemText>{row.name}</ListItemText></ListItemView>)}
</ScrollViewStyled>
);
}
render() {
return this.renderListView();
// return this.renderScrollView();
}
}
- 2、在 app 中目錄中新建 InlineStylePerformance.js
/* @flow weak */
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
ListView,
ScrollView
} from 'react-native';
import 'react-native-console-time-polyfill'
import data from './Data'
/**
* inLine style 性能測(cè)試
* @type {ListView}
*/
export default class InlineStylePerformance extends Component {
constructor(props) {
super(props);
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
this.state = {
dataSource: ds.cloneWithRows(data),
};
}
componentWillMount() {
console.log(`ListView - 渲染 ${data.length} 個(gè)組件`);
console.time('inline-style');
}
componentDidMount() {
console.timeEnd('inline-style');
}
renderRow = (row) =>(
<View style={styles.ListItemView}><Text style={styles.textStyle}>{row.name}</Text></View>
)
renderListView() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
enableEmptySections={true}
/>
);
}
renderScrollView() {
return (
<ScrollView>
{data.map((row, index) => (
<View style={styles.ListItemView} key={index}><Text style={styles.textStyle}>{row.name}</Text></View>
))}
</ScrollView>
);
}
render() {
return this.renderListView();
// return this.renderScrollView();
}
}
const styles = StyleSheet.create({
ListItemView: {
paddingTop: 5,
paddingBottom: 5,
borderBottomWidth: 1,
borderBottomColor: 'red',
},
textStyle:{
fontSize:18,
color:'red',
}
});
- 3、新建 Data.js
const data = []
for(let i=0;i<2000;i++){
data.push({name:`測(cè)試 === ${i}`})
}
export default data
- 4、測(cè)試,在 main.js 引入即可

在這里我們?cè)谀M器或是真機(jī)上開(kāi)啟遠(yuǎn)程 debug 調(diào)試,然后打開(kāi) chrome 調(diào)試就可以看到 console 打出的 log 了

打開(kāi) chrome 調(diào)試工具

經(jīng)過(guò)五次對(duì)比,得出以下結(jié)果

結(jié)論
- 由于我們是開(kāi)啟遠(yuǎn)程調(diào)試工具,所以和網(wǎng)絡(luò)也有關(guān)系,得出的結(jié)論不一定是最準(zhǔn)確的
- 但是也說(shuō)明了一些問(wèn)題 styled-components 目前的版本來(lái)說(shuō)「2.2.0」性還是比 in-line 樣式的性能稍有點(diǎn)差,
- styled-components 完全可以使用在項(xiàng)目中,并且相信以后的版本會(huì)逐漸縮小和 in-line 樣式的性能的微小差距
到此為止,我們就介紹完了 styled-components 的用法和性能比較,快上手試試吧
最近開(kāi)了公號(hào),以后文章內(nèi)容第一時(shí)間會(huì)發(fā)在公號(hào)中,希望大家關(guān)注,掃描以下二維碼即可關(guān)注
據(jù)說(shuō)每一個(gè)勤奮努力想成為非常牛 B 的人都會(huì)點(diǎn)個(gè)喜歡或轉(zhuǎn)發(fā)的