最近幾天學了幾個ReactNative組件,總覺得單純的學幾個組件進步慢,所以我打算做一些綜合性的小案例,練習下實戰,我從網上找到一個小案例
,感覺挺好,也學習了很多,代碼內容可能不太一樣,主要區別是:我把RN官方不推薦或者已經放棄了的組件進行了替換,如果有需要的可以互相參考下
接着上篇案例開始寫,這篇文章將會講解如何編寫輪播圖和列表
首先WYHome.js
代碼如下:
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
ListView
} from 'react-native';
import Request from '../Utils/WYRequest'
import WYSwiper from './Swiper/WYHomeSwiper'
import WYNewsCell from './WYNewsCell'
export default class WYHome extends Component {
static defaultProps = {
api_url: 'http://c.m.163.com/nc/article/headline/T1348647853363/0-20.html?from=toutiao&fn=1&prog=LTitleA&passport=&devId=nTM86EPlcxZu09VdpTEh6aR3%2B%2FQX6x8vHBD3ne3k5bbgOrg%2FIP5DcguSDmtYyWbs&offset=0&size=20&version=14.0&spever=false&net=wifi&lat=DUH4Hf95lyIDaAI03C3RSA%3D%3D&lon=HJ4tj6FL5wRHQxcf5GLEcg%3D%3D&ts=1470728804&sign=1H8K3yy9bMXakmxAlZ9P86meraJtjKQFz5vJuwhjNyl48ErR02zJ6%2FKXOnxX046I&encryption=1&canal=appstore',
key_word: 'T1348647853363'
};
// 構造
constructor(props){
super(props);
// 數據源
var ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
// 初始狀態
this.state = {
dataSource:ds,
// 廣告
headerAdArr:[],
// 判斷是否爲空
flag:false
};
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderHeader={this._renderHeader.bind(this)}
renderRow={this._renderRow.bind(this)}
>
</ListView>
);
}
componentDidMount() {
Request.get(this.props.api_url, (responseData) => {
// 取出數組
const dataArr = responseData[this.props.key_word];
// 臨時數組
var tempListArr = [], adArr = [];
// 遍歷數組
dataArr.forEach((value, index) => {
if(value.hasAd == 1 || value.hasHead == 1) {
adArr = value.ads;
} else {
tempListArr.push(value);
}
});
// 更新狀態,刷新UI
this.setState({
dataSource:this.state.dataSource.cloneWithRows(tempListArr),
headerAdArr:adArr,
flag:true
});
}, (error) => {
alert(error);
});
}
// 廣告
_renderHeader(){
// 防止空數據
if(!this.state.flag) return;
// 容錯
if(this.state.headerAdArr.length == 0) return;
return(
<WYSwiper dataArr={this.state.headerAdArr}></WYSwiper>
);
}
/**
* 返回具體的行
* @private
*/
_renderRow(rowData){
// 0. 防止空數據
if(!this.state.flag) return;
return(
<WYNewsCell model={rowData} navigator={this.props.navigation}/>
);
}
}
其中網絡解析WYRequest
抽離成一個幫助類:
module.exports = {
/**
* 基於fetch的get方法
* @method post
* @param {string} url
* @param {function} callback 請求成功回調
*/
get: function(url, successCallback, failCallback){
fetch(url)
.then((response) => response.json())
.then((responseText) => {
successCallback(responseText);
})
.catch(function(err){
failCallback(err);
});
}
};
輪播圖也單獨抽離爲一個組件,方便直接導入:
import React, { Component } from 'react'
import {
Text,
View,
Image,
Dimensions
} from 'react-native'
import Swiper from 'react-native-swiper'
const { width } = Dimensions.get('window');
export default class extends Component {
static defaultProps = {
dataArr: []
};
constructor(props) {
super(props);
// 初始狀態
this.state = {
currentTitle: ''
};
}
render() {
return (
<View>
<Swiper
style={styles.wrapper}
height={170}
onMomentumScrollEnd={(e, state, context) => this.setState({
// currentTitle: dataArr[state.index].title
})}
dot={<View style={{backgroundColor: 'rgba(255,255,255,1)', width: 5, height: 5, borderRadius: 4, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3}} />}
activeDot={<View style={{backgroundColor: 'orange', width: 8, height: 8, borderRadius: 4, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3}} />}
paginationStyle={{
bottom: 10, left: null, right: 10
}}
loop
>
{this._renderImage()}
</Swiper>
</View>
);
}
_renderImage(){
// 組件數組
var itemArr = [];
const dataArr = this.props.dataArr;
dataArr.forEach((value, index) => {
itemArr.push(
<View key={index} style={styles.slide}>
<Image
resizeMode='stretch'
style={styles.image}
source={{uri: value.imgsrc}}
defaultSource={{uri: 'placeholder'}}
/>
<View style={styles.indicatorViewStyle}>
<Text style={{color:'#fff'}}>{value.title}</Text>
</View>
</View>
);
});
// 返回組件
return itemArr;
}
}
const styles = {
wrapper: {
},
slide: {
flex: 1,
justifyContent: 'center',
backgroundColor: 'transparent'
},
slide1: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#9DD6EB'
},
slide2: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#97CAE5'
},
slide3: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#92BBD9'
},
text: {
color: '#fff',
fontSize: 30,
fontWeight: 'bold'
},
image: {
width,
flex: 1
},
indicatorViewStyle:{
width,
height:36,
backgroundColor:'rgba(0,0,0, 0.4)',
position:'absolute',
left:0,
bottom:0,
justifyContent:'center',
paddingLeft:5
}
};
自定義cellWYNewsCell.js
代碼如下:
import React, { Component, PropTypes } from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
Image,
PixelRatio
} from 'react-native';
var Dimensions = require('Dimensions');
var {width, height} = Dimensions.get('window');
export default class WYNewsCell extends Component {
// 構造
constructor(props){
super(props);
this.state = {
model: this.props.model,
navigator: this.props.navigator,
};
}
render() {
var model = this.state.model;
var hahah = this.state.navigator;
return (
<TouchableOpacity style={styles.cellStyle} onPress={() => {
hahah.navigate('WYNewsDetail', {title: model.title});
}}>
<Image
source={ {uri: model.imgsrc} }
defaultSource={ {uri: 'placeholder'} }
style={styles.imgStyle}
/>
<View style={styles.rightViewStyle}>
<Text
numberOfLines={2}
>
{model.title}
</Text>
<View style={styles.rightInnerViewStyle}>
<Text style={{color:'red', fontSize:14}}>{model.source}</Text>
<Text style={{color:'#333', fontSize:14}}>{model.ptime}</Text>
</View>
</View>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
cellStyle:{
borderBottomWidth: 1/PixelRatio.get(),
borderBottomColor: '#666',
flexDirection:'row',
padding:10
},
imgStyle:{
width:90,
height:90,
borderRadius:5,
marginRight:10
},
rightViewStyle:{
flex:1,
justifyContent:'space-around'
},
rightInnerViewStyle:{
flexDirection:'row',
justifyContent:'space-between'
}
});
module.exports = WYNewsCell;
點擊cell跳轉到詳情頁面:
render() {
var model = this.state.model;
var hahah = this.state.navigator;
return (
<TouchableOpacity style={styles.cellStyle} onPress={() => {
hahah.navigate('WYNewsDetail', {title: model.title});
}}>
<Image
source={{uri: model.imgsrc}}
defaultSource={{uri: 'placeholder'}}
style={styles.imgStyle}
/>
<View style={styles.rightViewStyle}>
<Text
numberOfLines={2}
>
{model.title}
</Text>
<View style={styles.rightInnerViewStyle}>
<Text style={{color:'red', fontSize:14}}>{model.source}</Text>
<Text style={{color:'#333', fontSize:14}}>{model.ptime}</Text>
</View>
</View>
</TouchableOpacity>
);
}
難點:
點擊cell跳轉詳情界面,需要將WYHome.js
文件當中的navigation
傳遞到cell當中:
<WYNewsCell model={rowData} navigator={this.props.navigation}/>
然後在cell當中就可以進行跳轉了。。。。
注意
要想進行跳轉必須在WYMain.js
文件中,對視圖進行註冊
const StackNavigators = StackNavigator({
TabNav: {
screen: TabNav,
},
// 跳轉註冊
WYNewsDetail: {
screen: WYNewsDetail,
}
});