本文出自:我的個(gè)人博客:http://www.cenzhijun.top/
最近幾天學(xué)了幾個(gè)ReactNative組件,總覺(jué)得單純的學(xué)幾個(gè)組件進(jìn)步慢仗处,所以我打算做一些綜合性的小案例泻帮,練習(xí)下實(shí)戰(zhàn)党晋,我從網(wǎng)上找到一個(gè)小案例
斧抱,感覺(jué)挺好,也學(xué)習(xí)了很多掐禁,代碼內(nèi)容可能不太一樣怜械,主要區(qū)別是:我把RN官方不推薦或者已經(jīng)放棄了的組件進(jìn)行了替換颅和,如果有需要的可以互相參考下
接著上篇案例開始寫,這篇文章將會(huì)講解如何編寫輪播圖和列表
源代碼下載
首先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'
};
// 構(gòu)造
constructor(props){
super(props);
// 數(shù)據(jù)源
var ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
// 初始狀態(tài)
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) => {
// 取出數(shù)組
const dataArr = responseData[this.props.key_word];
// 臨時(shí)數(shù)組
var tempListArr = [], adArr = [];
// 遍歷數(shù)組
dataArr.forEach((value, index) => {
if(value.hasAd == 1 || value.hasHead == 1) {
adArr = value.ads;
} else {
tempListArr.push(value);
}
});
// 更新?tīng)顟B(tài)缕允,刷新UI
this.setState({
dataSource:this.state.dataSource.cloneWithRows(tempListArr),
headerAdArr:adArr,
flag:true
});
}, (error) => {
alert(error);
});
}
// 廣告
_renderHeader(){
// 防止空數(shù)據(jù)
if(!this.state.flag) return;
// 容錯(cuò)
if(this.state.headerAdArr.length == 0) return;
return(
<WYSwiper dataArr={this.state.headerAdArr}></WYSwiper>
);
}
/**
* 返回具體的行
* @private
*/
_renderRow(rowData){
// 0. 防止空數(shù)據(jù)
if(!this.state.flag) return;
return(
<WYNewsCell model={rowData} navigator={this.props.navigation}/>
);
}
}
其中網(wǎng)絡(luò)解析WYRequest
抽離成一個(gè)幫助類:
module.exports = {
/**
* 基于fetch的get方法
* @method post
* @param {string} url
* @param {function} callback 請(qǐng)求成功回調(diào)
*/
get: function(url, successCallback, failCallback){
fetch(url)
.then((response) => response.json())
.then((responseText) => {
successCallback(responseText);
})
.catch(function(err){
failCallback(err);
});
}
};
輪播圖也單獨(dú)抽離為一個(gè)組件融虽,方便直接導(dǎo)入:
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);
// 初始狀態(tài)
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(){
// 組件數(shù)組
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 {
// 構(gòu)造
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;
點(diǎn)擊cell跳轉(zhuǎn)到詳情頁(yè)面:
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>
);
}
難點(diǎn):
點(diǎn)擊cell跳轉(zhuǎn)詳情界面,需要將WYHome.js
文件當(dāng)中的navigation
傳遞到cell當(dāng)中:
<WYNewsCell model={rowData} navigator={this.props.navigation}/>
然后在cell當(dāng)中就可以進(jìn)行跳轉(zhuǎn)了灼芭。。般又。彼绷。
注意
要想進(jìn)行跳轉(zhuǎn)必須在WYMain.js
文件中,對(duì)視圖進(jìn)行注冊(cè)
const StackNavigators = StackNavigator({
TabNav: {
screen: TabNav,
},
// 跳轉(zhuǎn)注冊(cè)
WYNewsDetail: {
screen: WYNewsDetail,
}
});