前言
這篇文章來介紹一下RN的屬性和狀態,以及在之前Hello World項目中已經出現的比如style等UI樣式的使用,之後我們就能使用這些來搭建一些簡單的UI介面。
還記得搭建環境的時候init的AwesomeProject項目吧,我們把它匯入到WebStorm中,下邊的內容都可以在裡邊改代碼。
關於如何運行,可以查看上一篇部落格,這裡就不贅述了。 Props(屬性)
大多數組件在建立時就可以使用各種參數來進行定製。用於定製的這些參數就稱為props(屬性)。
我們還是來對比Android中的屬性,比如TextView,常見的width,height,text,padding等等,ImageView的src,scaleType等,這些就是這些控制項的屬性。
那麼同樣的對於RN中的組件來說,它也有一系列與之對應的屬性,只不過寫法上有些不同罷了。
這裡我們舉個例子,以RN中的Image,對應Android中的ImageView,Image是用來展示圖片的組件。
那我們要用Image這個組件,首先就需要匯入進來:
import { AppRegistry, Image, StyleSheet, Text, View} from 'react-native';
我們在項目中將Image添加進來,之後就可以使用這個組件了。
我們在網上隨便找來一張圖片。然後將render(){}方法中的內容改為:
let pic={ uri: 'http://p4.music.126.net/cq1STvQ6q5b_Eg5grsTjYQ==/3275445147663993.jpg'};//載入網狀圖片,必須指定圖片尺寸return ( <View style={styles.container}> <Image source={pic} style={{width: 200, height: 200}} /> <Text style={styles.welcome}>This is a picture of Taylor Swift</Text> </View>);
然後我們運行一下,看一下效果。
代碼中<Image source={pic} style={{width: 200, height: 200}} />的source就是組件Image的屬性,指定要顯示的圖片的地址,這個屬性很類似ImageView的src屬性。
需要注意的一點:{pic}外圍有一層括弧,我們需要用括弧來把pic這個變數嵌入到JSX語句中。括弧的意思是括弧內部為一個js變數或運算式,需要執行後取值。因此我們可以把任意合法的JavaScript運算式通過括弧嵌入到JSX語句中。
跟我們直接把地址放進去是一樣的:
<Image source={{uri: 'http://p4.music.126.net/cq1STvQ6q5b_Eg5grsTjYQ==/3275445147663993.jpg'}} style={{width: 200, height: 200}} />
另外就是,Image組件在載入網狀圖片的時候,必須要指定寬高,這個先記著就行,關於圖片我們之後再做討論。
還有就是代碼中let pic={...}; 的let是ES6新增的命令,用來聲明變數。它的用法類似於var,但是所聲明的變數,只在let命令所在的代碼塊內有效。
前邊提到的import,class,const都是ES6**新增的用於聲明變數的命令**,加上ES5中已經有的var,function,共有6種聲明不同變數的命令。 樣式style
這裡style也是Image的屬性,而且幾乎全部的組件都有style這個屬性,這裡主要用來設定寬高,而且是直接在裡邊寫了{width: 200, height: 200},但是我們還記得這個項目裡邊,
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, },});
在外邊聲明style,然後再去引用是一樣的。
從這個層面上看,style更像是一個屬性的集合,裡邊是一個個的屬性,我們把需要設定的屬性放在裡邊,然後一句話去引用。這跟Android裡邊的style是非常類似的。
關於style,這些樣式名基本上是遵循了web上的CSS的命名,只是按照JS的文法要求使用了駝峰命名法,例如將background-color改為backgroundColor
style屬性可以是一個普通的JavaScript對象。這是最簡單的用法,就像樣本項目中那樣。還可以傳入一個數組——在數組中位置居後的樣式對象比居前的優先順序更高,這樣你可以間接實現樣式的繼承。
比如:
<Text style={[styles.container,styles.instructions]}>
重點:後聲明的屬性會覆蓋先聲明的同名屬性。
就是如果container和instructions,如果有同名的屬性,那麼instructions中的該屬性會起作用,而container中的該屬性則無效。 自訂群組件的屬性
我們在前一篇部落格中說過,可以extents Component來自訂群組件,自訂的組件也可以使用props,通過在不同的情境使用不同的屬性定製,可以盡量提高自訂群組件的複用範疇。只需在render函數中引用this.props,然後按需處理即可。
比如說我們不是這一張圖片,是好多明星的圖片,那我們在描述這張圖片的時候,如果還是寫一個個的<Text/>來說This is a picture of xxxx,那也太low了。所以,我們可以將下邊的描述單獨抽離出來成一個組件,而且將明星名字作為一個屬性,就可以複用了。
自訂一個組件:
class Description extends Component{ render() { return ( <Text style={styles.welcome}>This is a picture of {this.props.name}</Text> ); }}
然後這樣用:
return ( <View style={styles.container}> <Image source={pic} style={{width: 200, height: 200}} /> <Description name="Taylor Swift"/> </View>);
這裡的name就是我們自訂群組件Description的一個屬性,當然你可以用其他的詞,只要用的時候寫一樣的就OK。
重新reload一下,發現運行效果是一樣的。 this.props.children
2018/2/26更新
一般來說,我們使用this.props來擷取的屬性是和父組件傳入的屬性是對應的,但是有一個特殊的props需要注意,那就是this.props.children。
this.props.children常用於包含多個數量不確定子組件的父組件,來進行遍曆渲染。最常見的應用例子:app中首頁用於展示內容的banner或者swiper。
所以有以下幾個需要注意的點: 列表數量以及內容不確定,在父組件建立的時候才能確定 利用this.props.children從父組件擷取需要展示的清單項目內容 使用React.Children.map方法遍曆children,逐項設定,此方法返回一個數組對象,數組中的元素是child
一個簡單的用法樣本:
<Swiper> <View style={{backgroundColor: 'red'}}/> <View style={{backgroundColor: 'green'}}/> <View style={{backgroundColor: 'blue'}}/></Swiper>
Swiper的render方法
{ React.Children.map(this.props.children, (child) => { return ( {child} ) })}
State(狀態)
這裡藉助官網的說明:
我們使用兩種資料來控制一個組件:props和state。props是在父組件中指定,而且一經指定,在被指定的組件的生命週期中則不再改變。 對於需要改變的資料,我們需要使用state。
一般來說,你需要在constructor中初始化state(譯註:這是ES6的寫法,早期的很多ES5的例子使用的是getInitialState方法來初始化state,這一做法會逐漸被淘汰),然後在需要修改時調用setState方法。
通過上面的描述,我們發現思路呢和java代碼很類似啊,constructor顧名思義構造器,在構造器中給state初始化一個值,然後如果需要修改,就調用setState方法,也很好理解。
這裡給出官方例子,不過我們還在Description中寫:
class Description extends Component { constructor(props) { super(props); this.state = { showText: true }; // 每1000毫秒對showText狀態做一次取反操作 setInterval(() => { this.setState(previousState => { return { showText: !previousState.showText }; }); }, 1000); } render() { // 根據當前showText的值決定是否顯示text內容 // 這裡稍微改動一下 let text="This is a picture of " + this.props.name; let display = this.state.showText ? text : ' '; return ( <Text>{display}</Text> ); }}
reload一下,就可以看見這些字一閃一閃的了。
需要注意的地方:
setInterval,setTimeout等是定時器函數,這些之後會作瞭解。
如官網所說,我們一般不會在定時器函數(setInterval、setTimeout等)中來操作state,典型的情境是在接收到伺服器返回的新資料,或者在使用者輸入資料之後。
同樣的對比Android,這裡相當於類比網路請求資料,然後延時1s,去改變UI狀態。這樣是不是好理解多了。
更高端一點的,可以使用一些“狀態容器”比如Redux來統一管理資料流,這個以後再去慢慢瞭解。 結語
本篇文章過後,我們就瞭解了組件的屬性和狀態,以及為組件設定樣式style,包括自訂群組件。這樣我們能夠基本編寫出一些簡單的UI介面了。
好了,先這樣了,下篇再見。