本文出自:我的个人博客:http://www.cenzhijun.top/
最近几天学了几个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,
}
});