RN中布局樣式的寫法

介紹原始寫法 & 及其改進(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í)成本…… 所以還是不推薦……

參考鏈接:

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ò)還可以用~


其他參考閱讀:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末昂羡,一起剝皮案震驚了整個(gè)濱河市摔踱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌派敷,老刑警劉巖篮愉,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異甸赃,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)裁替,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門弱判,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)昌腰,“玉大人遭商,你說(shuō)我怎么就攤上這事捅伤。” “怎么了祠汇?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵可很,是天一觀的道長(zhǎng)诗力。 經(jīng)常有香客問(wèn)我,道長(zhǎng)苇本,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任圈澈,我火速辦了婚禮,結(jié)果婚禮上尘惧,老公的妹妹穿的比我還像新娘。我一直安慰自己喷橙,他們只是感情好啥么,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贰逾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪疙剑。 梳的紋絲不亂的頭發(fā)上氯迂,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天嚼蚀,我揣著相機(jī)與錄音僻孝,去河邊找鬼导帝。 笑死穿铆,一個(gè)胖子當(dāng)著我的面吹牛悴务,可吹牛的內(nèi)容都是我干的睹限。 我是一名探鬼主播譬猫,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼羡疗!你這毒婦竟也來(lái)了染服?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤叨恨,失蹤者是張志新(化名)和其女友劉穎柳刮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痒钝,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡秉颗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了送矩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚕甥。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖栋荸,靈堂內(nèi)的尸體忽然破棺而出菇怀,到底是詐尸還是另有隱情,我是刑警寧澤晌块,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布爱沟,位于F島的核電站,受9級(jí)特大地震影響匆背,放射性物質(zhì)發(fā)生泄漏呼伸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一钝尸、第九天 我趴在偏房一處隱蔽的房頂上張望括享。 院中可真熱鬧,春花似錦珍促、人聲如沸奶浦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至隙咸,卻和暖如春沐悦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背五督。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工藏否, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人充包。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓副签,卻偏偏與公主長(zhǎng)得像遥椿,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子淆储,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容