介紹原始寫法 & 及其改進(jìn)寫法一
還有比較流行的 styled-components在RN中的使用 & 及其改進(jìn)寫法二
1.原寫法
/**
* 原寫法
*/
const styles1 = StyleSheet.create({
item1:{
width:100,
height:200,
backgroundColor:'#66CCFF',
},
item2:{
width:100,
height:200,
backgroundColor:'#66CCFF',
},
item3:{
width:50,
height:100,
top:50,
left:25,
backgroundColor:'#66CCFF',
}
});
console.log('styles1 :',styles1);
原寫法的缺點(diǎn)在于變量不好引入,不好體現(xiàn)樣式間的關(guān)系锤躁,沒有計(jì)算表達(dá)式等……
2.改進(jìn)寫法一
看StyleSheet.create的代碼嘹吨,就是直接返回一個(gè)對(duì)象
//在react native 0.44版本中
var StyleSheet = {
create: function(styles) {
return styles;
},
那就可以不限于StyleSheet.create的寫法,可以比較自由的返回一個(gè)對(duì)象了性穿,下面給出一個(gè)我的簡(jiǎn)單例子:
/**
* 換一種寫法等限,簡(jiǎn)單引入了變量表達(dá)式
* 雖然還是沒有像iOS中 view.center / autolayout之類的寫法方便
* @returns {{}}
*/
function styles2Creator() {
let s = {};
let itemWidth = 100;
let itemHeight = 200;
//引用常量
s.item1 = {
width:itemWidth,
height:itemHeight,
backgroundColor:'#66CCFF',
};
//引用其他樣式的值
s.item2 = {
width:s.item1.width,
height:itemHeight,
backgroundColor:`${s.item1.backgroundColor}`,
};
//計(jì)算表達(dá)式
s.item3 = {
width: s.item2.width / 2,
height: s.item2.height / 2,
top:s.item2.height / 4,
left:s.item2.width / 4,
backgroundColor:s.item1.backgroundColor,
};
//樣式的繼承
s.item4 = {
...s.item3,
backgroundColor:'#FF00CC',
};
//帶參數(shù)
s.item5 = (top) => {
return {
...s.item3,
marginTop:top,
};
};
//帶參數(shù) + 缺省值
s.item6 = (top) => {
return {
...s.item3,
marginTop:top ? top : 10,
};
}
return s;
}
const style2 = styles2Creator();
//const style2 = StyleSheet.create(styles2Creator());
console.log('style2 :',style2);
運(yùn)行一下可以看到 log出來(lái)的style2和style1的屬性。
3. styled-components
號(hào)稱React 中的 CSS 最佳實(shí)踐,使用行內(nèi)樣式所宰,支持CSS。該第三方也也可用于RN畜挥。
react-native init
了個(gè)RN工程 寫了個(gè)簡(jiǎn)單的例子:
import React, {Component} from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image
} from 'react-native';
//需要 `npm install --save styled-components`
import styled from "styled-components/native";
//這里開始styled-components 式的樣式:
//styled-components的格式為: const [自定義變量名] = styled.[相應(yīng)的系統(tǒng)組件]`css表達(dá)式`;
//普通寫法 (不大寫開頭會(huì)報(bào)錯(cuò)……
const ListContainerView = styled.View`
width:360;
height:280;
background-color: #F0F2F5;
`;
//擴(kuò)展 (backgroundColor 和 background-color都可以
const ItemContainerView = ListContainerView.extend`
backgroundColor: #66CCFF;
flexDirection:row;
`;
//帶參數(shù)
const LeftImageContainerView = styled.View`
height:${props => props.primary ? 280 : 180};;
width:180;
background-color: #77BB00;
`;
//然后發(fā)現(xiàn)一個(gè)尷尬的事就是不知道怎么擴(kuò)展自定義組件 比如JDImage
//帶計(jì)算表達(dá)式
const LeftImageHeight = 280 - 10 *2;
const LeftImage = styled.Image`
margin-top:10;
margin-left:10;
width:${180 - 10 *2};
height:${LeftImageHeight};
background-color: #FFFFFF;
`;
//想要獲取另一個(gè)組件樣式LeftImage的高度 不能直接使用 ${LeftImage.height}
//因?yàn)?LeftImage返回的是 ? StyledNativeComponent()方法……
const RightContainerView = styled.View`
width:160;
height:${LeftImageHeight};
background-color: #FF00CC;
`;
export default class MyApp extends Component {
render() {
return (
<ItemContainerView >
<LeftImageContainerView primary>
{console.log('LeftImageContainerView.style:',LeftImageContainerView)}
<LeftImage source={{uri:'http://static.runoob.com/images/demo/demo2.jpg'}}/>
</LeftImageContainerView>
<RightContainerView></RightContainerView>
</ItemContainerView>
);
}
}
AppRegistry.registerComponent('MyApp', () => MyApp);
優(yōu)點(diǎn):
- react推薦的行內(nèi)樣式 css in js仔粥;
- 方便前端同學(xué)的寫法 可以完全使用CSS的書寫習(xí)慣
缺點(diǎn)和原始寫法的差不多,還對(duì)本身不是前端開發(fā)的人來(lái)說(shuō)帶來(lái)額外的學(xué)習(xí)成本…… 所以還是不推薦……
參考鏈接:
- styled-components React 中的 CSS 最佳實(shí)踐 | zhihu
- styled-components | 官方文檔
- Styled Components:讓樣式也成為組件 | alloyteam.
4.改進(jìn)寫法二
簡(jiǎn)單來(lái)講 styled-components 就是生成一個(gè)帶樣式的組件蟹但,完全可以吸收這種寫法 自己改進(jìn)RN中 躯泰,而不使用styled-components這個(gè)庫(kù)
結(jié)合 寫法一 和 styled-components的想法,給出一個(gè)簡(jiǎn)單例子:
import React, {Component} from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image
} from 'react-native';
//寫法二
function stylesCreator() {
let s = {};
let width = 360.0, height = 280.0;
s.ListContainerView = {
width: width,
height: height,
backgroundColor: '#F0F2F5',
};
s.ItemContainerView = {
width: width,
height: height,
backgroundColor: '#66CCFF',
flexDirection:'row',
};
console.log('s.ItemContainerView :',s.ItemContainerView);
s.LeftImageContainerView = {
height:height,
width:width / 2,
backgroundColor: '#77BB00',
};
s.LeftImage = {
marginTop:10,
marginLeft:10,
width: 180 - 10 *2,
height: s.LeftImageContainerView.height - 10*2,
backgroundColor: `#FFFFFF`,
};
s.RightContainerView = {
width: width / 2,
height: s.LeftImage.height,
backgroundColor: '#FF00CC',
};
return s;
}
const styles = stylesCreator();
//const styles = StyleSheet.create(stylesCreator());
//然后再結(jié)合 styled-components:
// 模擬 styled-components API
const styled = (Component, styler) => (props) => {
const style = typeof styler === 'function' ? styler(props) : styler;
return <Component {...props} style={[ style, props.style ]} />
}
// styled components
//同樣可以完成組件(帶樣式)的繼承 const RightContainerView = styled(LeftImageContainerView,styles.RightContainerView);
const ListContainerView = styled(View,styles.ListContainerView);
const ItemContainerView = styled(View,styles.ItemContainerView);
const LeftImageContainerView = styled(View,styles.LeftImageContainerView);
const LeftImage = styled(Image,styles.LeftImage);
const RightContainerView = styled(View,styles.RightContainerView);
export default class MyApp extends Component {
render() {
return (
<ItemContainerView >
<LeftImageContainerView primary>
{console.log('LeftImageContainerView.style:',LeftImageContainerView)}
<LeftImage source={{uri:'http://static.runoob.com/images/demo/demo2.jpg'}}/>
</LeftImageContainerView>
<RightContainerView></RightContainerView>
</ItemContainerView>
);
}
}
AppRegistry.registerComponent('MyApp', () => MyApp);
emmm 麦向,無(wú)需引入第三方庫(kù) 感覺好多了客叉。缺點(diǎn)當(dāng)然是不支持原CSS寫法兼搏。
5. react native 0.45
在0.45版本中運(yùn)行改進(jìn)寫法一時(shí),你可能看到style2在控制臺(tái)的輸出類似為:
//const style2 = StyleSheet.create(styles2Creator());
style2 :
{item1: 12, item2: 13, item3: 14, item4: 15, item5: 16, …}
item1:12
item2:13
item3:14
item4:15
item5:16
item6:17
__proto__:Object
這是怎么肥事!我的item對(duì)象怎么變成數(shù)字了件相!
別急夜矗,在0.45版本后StyleSheet代碼有所改變(其實(shí)我沒看具體哪個(gè)小版本改的 _(:зゝ∠)_
), StyleSheet.create改成:
//react native : 0.45.1
create<S: Styles>(obj: S): StyleSheet<S> {
const result: StyleSheet<S> = {};
for (var key in obj) {
StyleSheetValidation.validateStyle(key, obj);
result[key] = ReactNativePropRegistry.register(obj[key]);
}
return result;
},
//react native0.45.1 ReactNativePropRegistry.js
var objects = {};
var uniqueID = 1;
var emptyObject = {};
class ReactNativePropRegistry {
static register(object: Object): number {
var id = ++uniqueID;
if (__DEV__) {
Object.freeze(object);
}
objects[id] = object;
return id;
}
//多的就不看了……內(nèi)容不多各位有興趣自己看
通過(guò)看ReactNativePropRegistry代碼紊撕,StyleSheet將樣式對(duì)象儲(chǔ)存在objects
中,并返回uniqueID
比如取回原來(lái)的item,就可以這樣做:
import ReactNativePropRegistry from '../node_modules/react-native/Libraries/Renderer/src/renderers/native/ReactNativePropRegistry';
console.log("ReactNativePropRegistry.getByID(12): ",ReactNativePropRegistry.getByID(12));
console.log("ReactNativePropRegistry.getByID(style2. item1): ",ReactNativePropRegistry.getByID(style2. item1));
就可以通過(guò) ReactNativePropRegistry.getByID就可以取得樣式對(duì)象了惭缰。這可能對(duì)于之前的改進(jìn)寫法造成了一點(diǎn)小麻煩漱受,不過(guò)還可以用~
其他參考閱讀:
- react-native-css | github css + sass in rn
- rn-less | github css + less in rn
- React-Native 樣式管理方案淺談 | zhihu