react native在app開發(fā)上的一個優(yōu)勢就是組件化開發(fā),當有了足夠多的自定義組件后,可以很方便的將這些組件拼裝起來,開發(fā)效率提高很多。本文中將以一個picker為例子,來講如何包裝一個通用性很強的react native組件。本文的示例源碼可以在ReactNativeUIComponents下載。這個項目未來會不斷的維護加入更多實用的組件,也力求這個項目可以作為一個react native的示例項目,包含了react native開發(fā)中常用的router,navigator,code push等,可以作為參考。
</br>
可以在我的博客http://haiyangjiajian.com/交流更多相關內容。
picker的效果

其中picker要展示的內容,百度、搜狗、谷歌等均可以由父組件指定,其樣式也可以由父組件指定。
組件包裝
界面
本文封裝了一個叫Picker的組件。一般推薦通過定義defaultProps來告訴組件的調用者,可以傳入這個組件中的參數有哪些??梢钥吹娇梢詡魅氲膮涤衧tyle:組件樣式;animationType:動畫類型;transparent:是否透明;modalVisible:是否可見;dataArray:顯示的數據;title:標題。可以通過傳入這些參數,使這個組件擁有不同的樣式,顯示不同的數據。
static defaultProps = {
style: View.propTypes.style,
animationType: 'none',
transparent: true,
modalVisible: true,
dataArray: [],
title: 'title'
};
constructor(props) {
super(props);
this.state = {
dataSource: this._getDataSource(props.dataArray),
style: this.props.style,
animationType: this.props.animationType,
transparent: this.props.transparent,
modalVisible: this.props.modalVisible,
};
}
組件內部的渲染代碼如下,主體是一個Modal,然后是一個整體的view
<View style={[styles.modalContainer, {backgroundColor: 'rgba(0, 0, 0, 0.5)'}]}>
在這個view中主要有兩部分內容,一個是頂部的title,另一個是底部的listview,title顯示從父組件中傳入的標題,listview顯示傳入的dataArray。
<Modal
animationType={this.state.animationType}
transparent={this.state.transparent}
visible={this.state.modalVisible}
onRequestClose={() => {this._setModalVisible(false)}}>
<View style={[styles.modalContainer, {backgroundColor: 'rgba(0, 0, 0, 0.5)'}]}>
<View style={styles.viewContainer}>
<View style={styles.titleRow}>
<TouchableOpacity style={styles.cancelButton} onPress={() => {this._setModalVisible(false)}}>
<Image style={styles.image}
source={require('../img/icon_cancel_grey.png')}/>
</TouchableOpacity>
<Text style={[styles.titleText, styles.modalTitle]}>{this.props.title}</Text>
</View>
<View style={[{marginTop: 0, marginBottom: 0}]}/>
<ListView
style={styles.flex}
dataSource={this.state.dataSource}
renderRow={(rowData, sectionID, rowID) => this._renderRow(rowData, sectionID, rowID)}
renderScrollComponent={props => <RecyclerViewBackedScrollView {...props} />}
renderSeparator={(sectionID, rowID) => <View key={`${sectionID}-${rowID}`} style={[GlobalStyles.divider, {marginTop: 0, marginBottom: 0, marginLeft: 16}]}/>}
/>
</View>
</View>
</Modal>
listView中每一個cell的渲染
_renderRow(rowData, sectionID, rowID) {
return (
<TouchableHighlight onPress={() => this._pressRow(rowData, rowID)} underlayColor='gray'>
<View>
<View style={styles.row}>
<Text style={styles.rowTitle}>
{rowData.name}
</Text>
</View>
</View>
</TouchableHighlight>
);
}
下面是對這個組件調用的一個示例,puperseItems是一個格式化對象的數組,這個對象包含了name,id,url三個屬性
<Picker
title="選擇搜索引擎"
dataArray={purposeItems}
selectedData={(purpose) => {this.onPurposeSelected(purpose);}}
onHideModal={() => this.setState({purposeModalVisible: false})}
/>
至此界面的展示完畢
操作
這樣一個組件主要有兩種操作,點擊當前列和關閉modal,如下兩個函數,主要是調用了父組件傳遞進來的selectedData和onHideModal回調
_pressRow(rowData, rowID) {
this.props.selectedData && this.props.selectedData(rowData);
this.props.selectedIndex && this.props.selectedIndex(rowID);
}
_setModalVisible(visible) {
this.setState({modalVisible: visible});
if (visible) {
this.props.onShowModal && this.props.onShowModal();
} else {
this.props.onHideModal && this.props.onHideModal();
}
}
至此完成了一個組件的封裝,可以靈活的顯示父組件傳入的數據,并進行各種交互。
本文的示例源碼可以在ReactNativeUIComponents下載