React Native入门系列文章
第一篇:《小白扫盲篇》
第二篇:《如何编写样式》
第三篇:《如何手动开始写一个组件》
第四篇:《组件间通信》
第五篇:《踩过的坑》
第六篇:《实战写一个电影列表页》
第七篇:《网络通信和缓存处理》
第八篇:《Android打包发布》
第九篇:《如何从零开始学redux》
这一节介绍,如何用React Native实现一个电影列表页。主要目的就是,熟悉React Native基本语法。
一、先看下要做成什么样子
这里涉及到的知识点主要就是:1、熟悉FlatList控件使用规则;2、熟悉styles属性;3、熟悉React Native基本语法规则。
二、FlatList控件使用
<FlatList
style={styles.row}
numColumns={3}
keyExtractor={item => item.id}
data={movies.subjects}
renderItem={
({item}) =>
<Item
title={item.title}
image={item.images.medium}
stars={item.rating.stars}/>
}
/>
FlatList跟其他控件类似,可以通过设置styles属性来控制样式,numColumns指定一共有多少列,keyExtractor指定每一项的id,data指定数据源,renderItem用来为每一个Item设置参数。
其中,Item为自定义的控件。以下为Item.js的源码:
import React, {Component} from 'react';
import {
StyleSheet,
View,
AppRegistry,
Text,
Image,
Dimensions,
} from 'react-native';
const {width, height} = Dimensions.get('window');
const thirdWidth = width / 3;
const imageWidth = thirdWidth - 10 * 2;
const imageHeight = imageWidth / 0.697
export default class Item extends Component {
render() {
const {title, image, stars} = this.props;
return (
<View style={styles.root}>
<Image source={{uri:image}}
style={styles.image}/>
<Text style={styles.title} numberOfLines={1}>{title}</Text>
{renderStars(stars)}
</View>
);
}
}
const renderStars = (stars) => {
const total = 5;
let full, half, empty;
full = stars[0];
if (stars[1] === '5') {
full++;
half = 0;
empty = total - full;
} else {
half = 1;
empty = total - full - half;
}
const results = [];
let i;
for (i = 0; i < full; i++) {
results.push(
<Image
key={i}
style={styles.stars}
source={require("../img/star-full.png")}
/>);
}
if (half) {
results.push(
<Image
key={i}
style={styles.stars}
source={require("../img/star-half.png")}
/>);
i++;
}
for (let j = 0; j < empty; j++) {
results.push(
<Image
key={i+j}
style={styles.stars}
source={require("../img/star-empty.png")}
/>);
}
return (
<View style={styles.starsWrapper}>
{results}
</View>
);
}
const styles = StyleSheet.create({
root: {
width: imageWidth,
marginRight: 15,
marginTop: 20,
},
image: {
height: imageHeight,
width: imageWidth,
},
title: {
fontSize: 20,
fontWeight: 'bold',
textAlign: 'center',
},
starsWrapper: {
flexDirection: 'row',
},
stars: {
width: 10,
height: 10
}
});
三、熟悉styles属性:
该电影列表的布局思路如下:
1、首先给FlatList加一个paddingHorizontal属性,使得FlatList左右空出15;
2、设置图片宽度为屏幕宽度-4*间隔,设置图片高度为宽度的1.3倍;
const {width, height} = Dimensions.get('window');
const thirdWidth = width / 3;
const imageWidth = thirdWidth - 10 * 2;
const imageHeight = imageWidth / 0.697
在styles里把imageWidth和imageHeight赋值给height和width就行了。
3、给Item设置marginTop;给Text设置一行显示,api为numberOfLines;
四、熟悉React Native基本语法
1、定义控件的两种方式:
(1)函数法:
const renderStars = (stars) => {
const total = 5;
let full, half, empty;
full = stars[0];
if (stars[1] === '5') {
full++;
half = 0;
empty = total - full;
} else {
half = 1;
empty = total - full - half;
}
const results = [];
let i;
for (i = 0; i < full; i++) {
results.push(
<Image
key={i}
style={styles.stars}
source={require("../img/star-full.png")}
/>);
}
if (half) {
results.push(
<Image
key={i}
style={styles.stars}
source={require("../img/star-half.png")}
/>);
i++;
}
for (let j = 0; j < empty; j++) {
results.push(
<Image
key={i+j}
style={styles.stars}
source={require("../img/star-empty.png")}
/>);
}
return (
<View style={styles.starsWrapper}>
{results}
</View>
);
}
这个方法返回值为“星星评分”,使用时,只需要在render方法里:{renderStars(stars)}就可以了。
(2)组件法:
export default class App extends Component {
render() {
return (
<View>
<FlatList
style={styles.row}
numColumns={3}
keyExtractor={item => item.id}
data={movies.subjects}
renderItem={
({item}) =>
<Item
title={item.title}
image={item.images.medium}
stars={item.rating.stars}/>
}
/>
</View>
);
}
}
五、React Native中文网主推的页面跳转方式(React Navigation)
它的使用非常简单:
1、安装导航库:npm install --save react-navigation
2、引入 import {StackNavigator} from 'react-navigation';
3、StackNavigator的声明:
const App = StackNavigator({
List: {screen: List},
Detail: {screen: Detail},
});
以上代码就可完成路由的配置,可以看到我一共配置了两个页面。一个是产品列表页List.js,另一个是产品详情页Detail.js。
假设页面A要调到页面B,B再回退到A。
一、如何页面跳转?
1、从props中取出navigation的navigate方法(只要把组件加入到StackNavigator中,就会自动传入props);
const {navigate} = this.props.navigation;
2、通过navigate方法跳转
<View>
<FlatList
style={styles.row}
numColumns={3}
keyExtractor={item => item.id}
onRefresh={this.fetchdata}
refreshing={refreshing}
data={movies}
renderItem={
({item}) =>
<Item
title={item.title}
image={item.images.medium}
stars={item.rating.stars}
onPress={() => navigate('Detail',{
id: item.id,
})}/>
}
/>
</View>
3、通过navigate回退
(1)取出navigation的goBack方法
const {goBack} = this.props.navigation;
(2)调用goBack方法
<View>
<Text>电影详情页</Text>
<Text>电影id:{state.params.id}</Text>
<Text onPress={() => goBack()}>返回</Text>
</View>
二、页面跳转如何传参?
1、B如何接收值?
const {state} = this.props.navigation;
从navigation中取出state值,这个值就是页面跳转传过来的值
2、A如何收到B回退传过来的值?
(1)在A中定义一个callback方法,并且把callback方法传给B
a)在state中加一个childState
state = {
movies: movies.subjects,
refreshing: false,
childState: '',
};
b)在render中取出childState
const {movies, refreshing, childState} = this.state;
c)定义一个callback方法,在callback中setState
<View>
<Text>子组件返回的数据:{childState}</Text>
<FlatList
style={styles.row}
numColumns={3}
keyExtractor={item => item.id}
onRefresh={this.fetchdata}
refreshing={refreshing}
data={movies}
renderItem={
({item}) =>
<Item
title={item.title}
image={item.images.medium}
stars={item.rating.stars}
onPress={() => navigate('Detail',{
id: item.id,
callback: (data) => {
this.setState({
childState: data
})
}
})}/>
}
/>
</View>
callback: (data) => {
this.setState({
childState: data
})
}
})}/>
}
/>
</View>
(2)在B中传值
a)从navigation中取出state值
const {state, goBack} = this.props.navigation;
b)通过state的callback方法回调
return (
<View>
<Text>电影详情页</Text>
<Text>电影id:{state.params.id}</Text>
<Text onPress={() => {
state.params.callback("test");
goBack();
}}>返回</Text>
</View>
);
return (
<View>
<Text>电影详情页</Text>
<Text>电影id:{state.params.id}</Text>
<Text onPress={() => {
state.params.callback("test");
goBack();
}}>返回</Text>
</View>
);
六、总结
本文学习了React Native实战电影列表页,以及页面跳转间参数传递。
此处为demo地址,欢迎star,后续会持续更新