前言
构建项目
关于构建RN项目的环境,具体怎么做请参照#搭建开发环境 - React Native中文网新建项目
可以选择git clone一个空项目或者在react native的项目目录下执行:
react-native init DemoPro(项目名)
开始
- 设置数据源
这是拉取真正数据部分,这部分是通过fetch命令来抓取json数据,这里用到了豆瓣的一个开放的接口来提供json网络数据。然后用一个数组movies来接收解析后的数据,这个数据就是数据源。
constructor(props) {
super(props);
this.state = {
movieList: [], // 电影列表的数据源
loaded: false, // 用来控制loading视图的显示,当数据加载完成,loading视图不再显示
};
}
componentDidMount() {
this.loadDisplayingMovies();
}
loadDisplayingMovies() {
let that = this;
/// 查询正在上映的电影
function queryMovies(city, start, count) {
return "https://api.douban.com/v2/movie/in_theaters?city=" + city + "&start=" + start + "&count=" + count
}
fetch(queryMovies('深圳', 0, 30)).then((response) => response.json()).then((json) => {
console.log(json);
let movies = [];
for (let idx in json.subjects) {
let movieItem = json.subjects[idx];
let directors = ""; // 导演
for (let index in movieItem.directors) {
// 得到每一条电影的数据
let director = movieItem.directors[index];
// 将多个导演的名字用空格分隔开显示
if (directors === "") {
directors = directors + director.name
} else {
directors = directors + " " + director.name
}
}
movieItem["directorNames"] = directors;
// 拼装主演的演员名字,多个名字用空格分隔显示
let actors = "";
for (let index in movieItem.casts) {
let actor = movieItem.casts[index];
if (actors === "") {
actors = actors + actor.name
} else {
actors = actors + " " + actor.name
}
}
movieItem["actorNames"] = actors;
movies.push(movieItem)
}
that.setState({
movieList: movies,
loaded: true
})
}).catch((e) => {
console.log("加载失败");
that.setState({
loaded: true
})
}).done();
}
注意在这里componentDidMount()这个生命周期方法 ,一般而言这个方法只是在组件渲染之后调用一次,但是也有特殊情况,就是在state发生变化或者调用了setState()方法时,就会激发组件的重新渲染。也就是render方法会重新执行一遍:
- 调用数据源
在这里调用了上面所获取的数据源,用FlatList来展现一个电影列表。现在我们来让我们的应用能够渲染所有的数据而不是仅仅第一部电影。我们要用到的就是 FlatList 组件。
为什么建议把内容放到 FlatList 里?比起直接渲染出所有的元素,或是放到一个 ScrollView 里有什么优势?这是因为尽管 React 很高效,渲染一个可能很大的元素列表还是会很慢。FlatList会安排视图的渲染,只显示当前在屏幕上的那些元素。而那些已经渲染好了但移动到了屏幕之外的元素,则会从原生视图结构中移除(以提高性能)。
首先要做的事情:在文件最开头引入FlatList。
import React, { Component } from "react";
import { Image, FlatList, StyleSheet, Text, View } from "react-native";
现在来修改 render 函数。当我们已经有了数据之后,渲染一个包含多个电影信息的 FlatList,而不仅仅是单个的电影:
render() {
if (!this.state.loaded) {
return (
<View style={styles.loadingView}>
<ActivityIndicator animating={true} size="small"/>
<Text style={{color: '#666666', paddingLeft: 10}}>努力加载中</Text>
</View>
)
}
return (
<FlatList
data={this.state.movieList}
renderItem={this._renderItem}
keyExtractor={(item) => item.id}
/>
)
}
_renderItem = (item) => {
return (
<MovieItemCell movie={item.item} onPress={() => {
Alert.alert('点击了电影----' + item.item.title);
console.log('点击了电影----' + item.item.title);
}}/>
)
};
-
设置Item 显示数据
走到这里就是设置Item的样式和布局了,现在我们已经成功的把我们的数据渲染出来了,下面让我们把它弄的更好看一些。就像这样:
import React, {Component} from 'react';
import {TouchableHighlight, View, Image, Text, StyleSheet} from 'react-native';
export default class MovieItemCell extends Component {
render() {
let {movie} = this.props;
let hasAverageScore = (movie.rating.average !== 0);
return (
<TouchableHighlight onPress={this.props.onPress}>
<View style={styles.container}>
<Image
source={{uri: movie.images.large}}
style={styles.thumbnail}
/>
<View style={styles.rightContainer}>
<Text style={styles.title}>{movie.title}</Text>
<Text style={styles.year}>{movie.year}</Text>
{
hasAverageScore ?
(<View style={styles.horizontalView}>
<Text style={styles.titleTag}>评分:</Text>
<Text style={styles.score}>{movie.rating.average}</Text>
</View>) :
(<View style={styles.horizontalView}>
<Text style={styles.titleTag}>暂无评分</Text>
</View>)
}
<View style={styles.horizontalView}>
<Text style={styles.titleTag}>导演:</Text>
<Text style={styles.name}>{movie.directorNames}</Text>
</View>
<View style={styles.horizontalView}>
<Text style={styles.titleTag}>主演:</Text>
<Text style={styles.name}>{movie.actorNames}</Text>
</View>
</View>
</View>
</TouchableHighlight>
)
}
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
justifyContent: 'center',
backgroundColor: '#F5FCFF',
padding: 10,
borderBottomWidth: 1,
borderColor: ‘#e0e0e0’
},
thumbnail: {
width: 110,
height: 150,
backgroundColor: '#f0f0f0',
},
rightContainer: {
flex: 1,
paddingLeft: 10,
paddingTop: 5,
paddingBottom: 5
},
title: {
fontSize: 16,
fontWeight: 'bold',
color: '#333333',
textAlign: 'left',
},
year: {
textAlign: 'left',
color: '#777777',
marginTop: 10,
},
horizontalView: {
flexDirection: 'row',
marginTop: 10
},
titleTag: {
color: '#666666',
},
score: {
color: '#ff8800',
fontWeight: 'bold',
},
name: {
color: '#333333',
flex: 1
},
});
为了实现一个完整功能的应用,接下来其实还有一些工作要做,譬如:添加导航器,搜索,加载更多,等等等等。