React Native學(xué)習(xí)記錄
參考資料:
react native中文網(wǎng)
http://reactnative.cn/docs/0.31/getting-started.html
react native專題博客
http://www.lcode.org/react-native/
- 使用 :
- 搭建開發(fā)環(huán)境(參照官網(wǎng))
- 開發(fā)工具(VS Code + vscode-react-native插件)
創(chuàng)建項(xiàng)目 (命令)
- react-native init **項(xiàng)目名
- cd **項(xiàng)目名
- 運(yùn)行 react-native run-android
- 手動(dòng)運(yùn)行 cd **項(xiàng)目名
我的目錄:
參照官網(wǎng)開始寫列子
主要實(shí)現(xiàn)的功能如下:
Props (屬性)
組件在創(chuàng)建時(shí)就可以使用各種參數(shù)來進(jìn)行定制。用于定制的這些參數(shù)就稱為Props(屬性)。
比如給Image設(shè)置圖片資源的時(shí)候,source 就是一個(gè)屬性;自定義的組件也可以使用props瘩扼。
通過在不同的場(chǎng)景使用不同的屬性定制崇堵,可以盡量提高自定義組件的復(fù)用范疇胞枕。只需在render函數(shù)中引用this.props齐遵,然后按需處理即可谋逻。
比如下邊的代碼: 實(shí)現(xiàn)簡(jiǎn)單的Text,Image的顯示和屬性的調(diào)用,以及自定義的屬性的使用;
class PropsTest extends React.Component {
// 構(gòu)造
constructor(props) {
super(props);
// 初始狀態(tài)
this.navigator = this.props.navigator;
}
render(){
let pic = {
uri: 'http://upload.ct.youth.cn/2015/0707/1436200566521.jpg'
};
//省略其他圖片
return (
<View style={styles.viewStyle}>
<ToolBar navigator={this.props.navigator} title={'Props(屬性)'}/>
<Text style={styles.texrStyle}>濱崎步</Text>
<Image source= {pic} style={{width:400 ,height: 240 }}></Image>
<Text style={styles.texrStyle}>自定義2張排列</Text>
<Greeting2 imageUrl1={pic1} imageUrl2={pic2} />
<Text style={styles.texrStyle}>自定義3張排列</Text>
<Greeting3 imageUrl3={pic3} imageUrl4={pic4} imageUrl5={pic5} />
</View>
);
}
}
class Greeting2 extends React.Component {
render(){
return (
<View style={styles.greetingView}>
<Image source= {this.props.imageUrl1} style={{width: 160, height: 80}}></Image>
<Image source= {this.props.imageUrl2} style={{width: 160, height: 80}}></Image>
</View>
);
}
}
class Greeting3 extends React.Component {
render(){
return (
<View style={styles.greetingView}>
<Image source= {this.props.imageUrl3} style={{width: 100, height: 80}}></Image>
<Image source= {this.props.imageUrl4} style={{width: 100, height: 80}}></Image>
<Image source= {this.props.imageUrl5} style={{width: 100, height: 80}}></Image>
</View>
);
}
}
運(yùn)行效果如下:
State(狀態(tài))
使用State控制需要改變的數(shù)據(jù)
實(shí)現(xiàn)一個(gè)點(diǎn)擊按鈕改變圖片和文字的代碼,再次點(diǎn)擊再次改變.使用State控制showText,通過點(diǎn)擊事件根據(jù)showText的值設(shè)置空間的信息.
class StateTest extends React.Component {
constructor(props) {
super(props);
this.navigator = this.props.navigator;
this.state = {showText : true};
}
render(){
let textContent = this.state.showText ? '濱崎步' : '宇多田光';
var url = this.state.showText ? 'http://upload.ct.youth.cn/2015/0707/1436200566521.jpg' : 'http://i5.qhimg.com/t01d8897aa3b7010d89.jpg';
let imageUri = {
uri: url
}
return(
<View style={styles.viewStyle}>
<ToolBar navigator={this.props.navigator} title={'State(狀態(tài))'}/>
<Text style={styles.texrStyle}>{textContent}</Text>
<Image source={imageUri} style={{width:400 ,height: 240 }}></Image>
<TouchableHighlight style={styles.touchAbleBg} >
<Text style={[styles.textColor,{fontSize:18}]} onPress={() => this._setStateView()}>
改變文字和圖片
</Text>
</TouchableHighlight>
</View>
);
}
_setStateView(){
if(this.state.showText){
this.setState({showText: false });
}else{
this.setState({showText: true });
}
}
}
運(yùn)行效果如下:
樣式
關(guān)于樣式的設(shè)置在代碼頁面基本都會(huì)用到一些,參照網(wǎng)
處理文本輸入
TextInput是一個(gè)允許用戶輸入文本的基礎(chǔ)組件。它有一個(gè)名為onChangeText的屬性挠他,此屬性接受一個(gè)函數(shù)扳抽,而此函數(shù)會(huì)在文本變化時(shí)被調(diào)用。另外還有一個(gè)名為onSubmitEditing的屬性殖侵,會(huì)在文本被提交后(用戶按下軟鍵盤上的提交鍵)調(diào)用贸呢。
我們實(shí)現(xiàn)的是根據(jù)輸入的文字,在Text控件上顯示輸入的內(nèi)容,代碼下:
class InputTest extends React.Component {
constructor(props){
super(props);
this.state = {text:''};
}
render(){
return(
<View>
<ToolBar navigator={this.props.navigator} title={'TextInput(文本輸入)'}/>
<TextInput
style={[{height: 40} , {padding: 10}]}
placeholder="這是輸入提示"
onChangeText={(text) => this.setState({text})}
/>
<Text style={{padding: 10, fontSize: 42}}>
{this.state.text}
</Text>
</View>
);
}
}
效果就不展示了...
ScrollView滾動(dòng)視圖
關(guān)于滾動(dòng)視圖和安卓用法區(qū)別不大
這里有一個(gè)坑需要注意,就是在view嵌套的時(shí)候會(huì)出現(xiàn)不滾動(dòng)的情況, 這里的話根布局的view 需要設(shè)置flex: 1才可以(類似安卓的權(quán)重屬性).同樣適用于listview布局.
先看代碼
class ScrollViewRe extends React.Component {
render(){
let imageUrl = {
uri: 'http://i5.qhimg.com/t01d8897aa3b7010d89.jpg'
}
return(
<ScrollView>
<Text style={{fontSize:20}}>滾動(dòng)視圖展示</Text>
<Image source={imageUrl} style={styles.imageStyle}/>
<Image source={imageUrl} style={styles.imageStyle}/>
<Image source={imageUrl} style={styles.imageStyle}/>
<Image source={imageUrl} style={styles.imageStyle}/>
</ScrollView>
);
}
}
const styles = StyleSheet.create ({
viewStyle: {
flex: 1, //必須設(shè)置 ,否則不能滾動(dòng)
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center'
},
imageStyle: {
width: 240,
height: 400
}
});
運(yùn)行效果如下:
ListView 列表
這個(gè)效果就是列表, 有兩個(gè)屬性必須設(shè)置的 (dataSource和renderRow ). 一個(gè)時(shí)列表數(shù)據(jù),一個(gè)時(shí)渲染的item
這里只是展示,沒有實(shí)現(xiàn)更多功能, 后續(xù)實(shí)現(xiàn)更新和加載的功能;
class ListViewTest extends React.Component {
constructor(props){
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
var data = [20];
for (var index = 0; index < 20; index++) {
data[index] = 'TiaoPi' + index;
}
this.state = {
dataSource: ds.cloneWithRows(data)
}
}
_listItem(textData){
let imageUrl = {
uri: 'http://i5.qhimg.com/t01d8897aa3b7010d89.jpg'
}
return(
<View style={{flexDirection: 'row'}} >
<Image source={imageUrl} style={styles.imageStyle}></Image>
<Text>{textData}</Text>
</View>
);
}
render(){
return(
<View style={styles.viewStyle}>
<ToolBar navigator={this.props.navigator} title={'ListView(列表)'}/>
<ListView
dataSource={this.state.dataSource}
renderRow={this._listItem.bind(this)}
/>
</View>
);
}
}
效果如下:
ViewPager (使用開源項(xiàng)目實(shí)現(xiàn))
react-native-swiper (https://github.com/leecade/react-native-swiper)
跟安卓viewpager類似 下邊只是簡(jiǎn)單實(shí)現(xiàn)效果,后續(xù)繼續(xù)學(xué)習(xí)
import Swiper from 'react-native-swiper';
class ViewPagerTest extends React.Component {
render(){
let pic3 = {
uri: 'http://img0.ph.126.net/V946kkk3daLMuEuHNDPJAQ==/732679364477853939.png'
};
let pic4 = {
uri: 'http://i5.qhimg.com/t01d8897aa3b7010d89.jpg'
};
let pic5 = {
uri: 'http://www.qzhxw.com/d/file/p/0905/69ad0d2bb46f815a9550ad20c07494b4.jpg'
};
return(
<View style={styles.viewStyle}>
<ToolBar navigator={this.props.navigator} title={'ViewPager(開源控件)'}/>
<Swiper style={styles.wrapper} showsButtons={false}>
<View style={styles.slide1}>
<Image source={pic3} style={styles.imageStyle}></Image>
<Text style={styles.text}>第1張</Text>
</View>
<View style={styles.slide2}>
<Image source={pic4} style={styles.imageStyle}></Image>
<Text style={styles.text}>第2張</Text>
</View>
<View style={styles.slide3}>
<Image source={pic5} style={styles.imageStyle}></Image>
<Text style={styles.text}>第3張</Text>
</View>
</Swiper>
</View>
);
}
}
效果如下 :
ListView上下拉刷新
基于RN提供的下拉刷新組件(refreshControl)和ListView的onEndReached方法實(shí)現(xiàn)
var myData = [];
class PullRefreshTest extends React.Component{
constructor (props){
super(props);
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
for (var index = 0; index < 20; index++) {
myData.push('TiaoPi' + index);
}
this.state = ({
dataSource:ds.cloneWithRows(myData),isRefreshing : false
});
}
componentWillMount() {
this._genRows();
}
render(){
return(
<View style={styles.viewStyle}>
<ToolBar navigator={this.props.navigator} title={'PullRefreshListView'}/>
<ListView
enableEmptySections={true}
dataSource={this.state.dataSource}
renderRow={this._listItem.bind(this)}
onEndReached={this._toEnd.bind(this)}
onEndReachedThreshold={0}
refreshControl={
<RefreshControl
refreshing={this.state.isRefreshing}
onRefresh={this._onRefresh.bind(this)}
tintColor="#ff0000"
title="Loading..."
titleColor="#00ff00"
colors={['#ff0000', '#00ff00', '#0000ff']}
progressBackgroundColor="#ffff00"
/>}
/>
</View>
);
}
_listItem(textData){
let imageUrl = {
uri: 'http://i5.qhimg.com/t01d8897aa3b7010d89.jpg'
}
return(
<View style={{flexDirection: 'row'}} >
<Image source={imageUrl} style={styles.imageStyle}></Image>
<Text style={{fontSize:20}}>{textData}</Text>
</View>
);
}
_onRefresh(){
this.setState({isRefreshing: true});
myData = [];
for (var index = 0; index < 5; index++) {
myData.push('刷新后的TiaoPi' + index);
}
this.setState({
isRefreshing: false,
dataSource: this.state.dataSource.cloneWithRows(myData),
});
}
_refreshData(){
for (var index = 0; index < 10; index++) {
myData.push('TiaoPi' + index);
}
this._setDataSource(myData);
}
_toEnd(){
this._genRows();
}
_setDataSource(data){
this.setState({
dataSource: this.state.dataSource.cloneWithRows(data),
});
}
_genRows(){
for (var index = 0; index < 10; index++) {
myData.push('TiaoPi' + index);
}
this._setDataSource(myData);
}
}
側(cè)滑菜單實(shí)現(xiàn)
DrawerLayoutAndroid 實(shí)現(xiàn)側(cè)滑菜單
class DrawerLayoutTest extends React.Component {
render(){
let pic3 = {
uri: 'http://img0.ph.126.net/V946kkk3daLMuEuHNDPJAQ==/732679364477853939.png'
};
return (
<DrawerLayoutAndroid
ref='MyDrawerLayout'
drawerWidth={300}
drawerPosition={DrawerLayoutAndroid.positions.Left}
renderNavigationView={() => <DrawerView />}
>
<View>
<ToolBar navigator={this.props.navigator} title={'側(cè)滑菜單展示'}/>
<View style={{flex: 1, alignItems: 'center'}}>
<Text style={{fontSize: 20}}>這是頁面</Text>
<Image source={pic3} style={{width: 240,height: 320}}></Image>
<TouchableHighlight style={styles.touchAbleBg} onPress={() => this._drawerLayoutClick()}>
<Text style={[styles.textColor,{fontSize:18}]}>
菜單
</Text>
</TouchableHighlight>
</View>
</View>
</DrawerLayoutAndroid>
);
}
_drawerLayoutClick(){
this.refs.MyDrawerLayout.openDrawer();
}
}
class DrawerView extends React.Component {
render(){
let pic3 = {
uri: 'http://img0.ph.126.net/V946kkk3daLMuEuHNDPJAQ==/732679364477853939.png'
};
return(
<View style={{flex: 1, alignItems: 'center'}}>
<Image source={pic3} style={{width: 300,height: 400}}></Image>
<Text style={{fontSize: 20}}>這是菜單</Text>
</View>
);
}
}
拉風(fēng)出游首頁
先看代碼 : 只顯示實(shí)現(xiàn)代碼, 樣式的代碼忽略了
class LafengHome extends React.Component {
render(){
return (
<View style={{flex: 1}}>
<ToolBar navigator={this.props.navigator} title={'拉豐出游'}/>
<ScrollView>
<HeadViewPager />
<Image source={require('./img/home_img_lvbao.png')} style={styles.centerImageStyle}></Image>
<Image source={require('./img/top_item.png')} style={styles.centerImageStyle2}></Image>
<HomeListView />
</ScrollView>
</View>
);
}
}
class HomeListView extends React.Component {
constructor(props){
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
var datas = [{title: '游艇', content: '游艇業(yè)務(wù)內(nèi)容'},
{title: '飛機(jī)', content: '飛機(jī)業(yè)務(wù)介紹'},
{title: '豪車', content: '豪車業(yè)務(wù)介紹'}]
this.state = {
dataSource: ds.cloneWithRows(datas)
}
}
render(){
return(
<ListView
dataSource={this.state.dataSource}
renderRow={this._listItem.bind(this)}
/>
);
}
_listItem(datas){
let imageUrl = {
uri: 'http://img0.ph.126.net/V946kkk3daLMuEuHNDPJAQ==/732679364477853939.png'
}
return(
<View style={{flexDirection: 'row'}} >
<Image source={imageUrl} style={styles.imageBg}>
<View style={styles.viewBg}>
<Text style={styles.itemText1}>{datas.title}</Text>
<Text style={styles.itemText2}>{datas.content}</Text>
</View>
</Image>
</View>
);
}
}
class HeadViewPager extends React.Component {
render(){
let pic3 = {
uri: 'http://img0.ph.126.net/V946kkk3daLMuEuHNDPJAQ==/732679364477853939.png'
};
let pic4 = {
uri: 'http://i5.qhimg.com/t01d8897aa3b7010d89.jpg'
};
let pic5 = {
uri: 'http://www.qzhxw.com/d/file/p/0905/69ad0d2bb46f815a9550ad20c07494b4.jpg'
};
return(
<Swiper style={styles.wrapper} showsButtons={false} height={240} autoplay={true}>
<View>
<Image source={pic3} style={styles.pagerImageStyle}></Image>
</View>
<View>
<Image source={pic4} style={styles.pagerImageStyle}></Image>
</View>
<View>
<Image source={pic5} style={styles.pagerImageStyle}></Image>
</View>
</Swiper>
);
}
}
最后給上運(yùn)行效果: