本文中我们将创建一个简单的电影应用,这个应用将从Rotten Tomatoes网站抓取目前正在上映的最新的25部电影,并将它们展示在一个ListView中。
一、伪造数据
在我们开始编写代码从Rotten Tomatoes网站抓取数据之前,我们先来伪造一些数据,以便我们可以马上体验一下React Native。我们一般会在JS文件的顶部声明常量,并在后面使用。在index.ios.js中添加以下代码:
var MOCKED_MOVIES_DATA = [ {title: 'Title', year: '2015', posters: {thumbnail: 'http://i.imgur.com/UePbdph.jpg'}}, ];
二、渲染一部电影
我们会渲染电影的标题、年份以及海报缩略图。由于缩略图在React Native中是一个Image组件,所以我们需要将Image组件加到React的依赖项中。
var { AppRegistry, Image, StyleSheet, Text, View, } = React;
现在我们来修改render函数,以便我们可以渲染上面的模拟数据。
render: function() { var movie = MOCKED_MOVIES_DATA[0]; return ( <View style={styles.container}> <Text>{movie.title}</Text> <Text>{movie.year}</Text> <Image source={{uri: movie.posters.thumbnail}} style={styles.thumbnail} /> </View> ); }
同时我们还需要修改styles,用来将样式应用到相应的组件上。
var styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, thumbnail: { width: 53, height: 81, }, });
按下cmd+R,此时的电影标题、年份以及海报缩略图已经渲染出来了。
三、修改样式,将文字放在图片的右侧
接下来,我们把文字放在图片的右侧,同时让标题字体大一些并居中显示。
修改render函数,添加另一个View,这是为了让我们的组件在最外层的组件中垂直居中显示。
render: function() { var movie = MOCKED_MOVIES_DATA[0]; return ( <View style={styles.container}> <Image source={{uri: movie.posters.thumbnail}} style={styles.thumbnail} /> <View style={styles.rightContainer}> <Text style={styles.title}>{movie.title}</Text> <Text style={styles.year}>{movie.year}</Text> </View> </View> ); }
同时我们还需要修改styles,用来将样式应用到相应的组件上。
var styles = StyleSheet.create({ container: { flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, thumbnail: { width: 53, height: 81, }, rightContainer: { flex: 1, }, title: { fontSize: 20, marginBottom: 8, textAlign: 'center', }, year: { textAlign: 'center', }, });
按下cmd+R来查看更新之后的视图。
四、抓取真实数据
将下面的常量放在文件的顶部,用来创建一个请求数据使用的REQUEST_URL:
var API_KEY = '7waqfqbprs7pajbz28mqf6vz'; var API_URL = 'http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json'; var PAGE_SIZE = 25; var PARAMS = '?apikey=' + API_KEY + '&page_limit=' + PAGE_SIZE; var REQUEST_URL = API_URL + PARAMS;
为我们的应用添加初始状态,这样我们可以通过检查this.state.movies === null来确定电影数据有没有被加载。当电影数据返回时,我们可以通过this.setState({movies: moviesData})来设置数据。
将下面的代码添加到render函数之前:
getInitialState: function() { return { movies: null, }; },
我们想要在组件完成加载后发送请求,componentDidMount是React组件中的一个函数,它只会在组件加载完成后被调用一次。
componentDidMount: function() { this.fetchData(); },
接下来添加组件中会用到的fetchData函数,这个函数将负责处理数据的抓取。你需要做的仅仅是在promise完成解析后调用this.setState({movies: data})。因为setState会触发重新渲染,而此时render函数会注意到this.state.movies不再是null。
注意一定要在promise链的最后调用done(),否则错误信息可能会被忽略。
fetchData: function() { fetch(REQUEST_URL) .then((response) => response.json()) .then((responseData) => { this.setState({ movies: responseData.movies, }); }) .done(); },
现在修改render函数,如果电影数据还没有返回的话,就渲染一个loading视图,否则将渲染第一部电影。
render: function() { if (!this.state.movies) { return this.renderLoadingView(); } var movie = this.state.movies[0]; return this.renderMovie(movie); }, renderLoadingView: function() { return ( <View style={styles.container}> <Text> Loading movies... </Text> </View> ); }, renderMovie: function(movie) { return ( <View style={styles.container}> <Image source={{uri: movie.posters.thumbnail}} style={styles.thumbnail} /> <View style={styles.rightContainer}> <Text style={styles.title}>{movie.title}</Text> <Text style={styles.year}>{movie.year}</Text> </View> </View> ); },
按下cmd+R,首先会看到loading页面
电影数据返回后,就会渲染第一部从Rotten Tomatoes获取过来的电影。
五、显示完整的电影列表
现在我们来修改应用,将所有的数据渲染在一个ListView组件中,而不是只渲染一部电影。
这里使用ListView是因为ListView会自动渲染视线之内的视图,而那些在屏幕之外的视图会被暂时移除。
这里既然用到了ListView,我们就需要将ListView组件加到React的依赖项中。
var { AppRegistry, Image, ListView, StyleSheet, Text, View, } = React;
接下来修改render函数,一旦数据返回就可以在ListView里面渲染数据:
render: function() { if (!this.state.loaded) { return this.renderLoadingView(); } return ( <ListView dataSource={this.state.dataSource} renderRow={this.renderMovie} style={styles.listView} /> ); },
DataSource是ListView的一个接口,作用是决定哪些行会改变。
接下来,我们需要在getInitialState的返回对象上添加一个空的dataSource,我们不能再使用this.state.movies防止数据被存储两次。我们可以使用this.state.loaded来判断数据抓取是否结束。
getInitialState: function() { return { dataSource: new ListView.DataSource({ rowHasChanged: (row1, row2) => row1 !== row2, }), loaded: false, }; },
我们还需要修改fetchData来更新state:
fetchData: function() { fetch(REQUEST_URL) .then((response) => response.json()) .then((responseData) => { this.setState({ dataSource: this.state.dataSource.cloneWithRows(responseData.movies), loaded: true, }); }) .done(); },
最后,我们在styles中为ListView组件添加样式:
listView: { paddingTop: 20, backgroundColor: '#F5FCFF', },
下面是最终的效果图:
六、本文最终完整的源码
'use strict'; var React = require('react-native'); var API_KEY = '7waqfqbprs7pajbz28mqf6vz'; var API_URL = 'http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json'; var PAGE_SIZE = 25; var PARAMS = '?apikey=' + API_KEY + '&page_limit=' + PAGE_SIZE; var REQUEST_URL = API_URL + PARAMS; var { AppRegistry, Image, ListView, StyleSheet, Text, View, } = React; var Movie = React.createClass({ getInitialState: function() { return { dataSource: new ListView.DataSource({ rowHasChanged: (row1, row2) => row1 !== row2, }), loaded: false, }; }, componentDidMount: function() { this.fetchData(); }, fetchData: function() { fetch(REQUEST_URL) .then((response) => response.json()) .then((responseData) => { this.setState({ dataSource: this.state.dataSource.cloneWithRows(responseData.movies), loaded: true, }); }) .done(); }, render: function() { if (!this.state.loaded) { return this.renderLoadingView(); } return ( <ListView dataSource={this.state.dataSource} renderRow={this.renderMovie} style={styles.listView} /> ); }, renderLoadingView: function() { return ( <View style={styles.container}> <Text> Loading movies... </Text> </View> ); }, renderMovie: function(movie) { return ( <View style={styles.container}> <Image source={{uri: movie.posters.thumbnail}} style={styles.thumbnail} /> <View style={styles.rightContainer}> <Text style={styles.title}>{movie.title}</Text> <Text style={styles.year}>{movie.year}</Text> </View> </View> ); }, }); var styles = StyleSheet.create({ container: { flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, thumbnail: { width: 53, height: 81, }, rightContainer: { flex: 1, }, title: { fontSize: 20, marginBottom: 8, textAlign: 'center', }, year: { textAlign: 'center', }, listView: { paddingTop: 20, backgroundColor: '#F5FCFF', }, }); AppRegistry.registerComponent('Movie', () => Movie);
相关推荐
采用ReactNative和Exponent构建的可展开列表集合组件
用react-native构建的简单的十五益智游戏。滑动瓷砖以将它们排列整齐。 效果展示: ... 更多详情、使用方法,请下载后阅读README.md文件
Weather-App-React-Native:采用react-native构建的天气预报iOS App
使用React Native和News API构建的简单跨平台新闻应用
第3章 构建你的第一个应用 13 3.1 搭建环境 13 3.2 创建一个新的应用 17 3.3 探索示例代码 24 3.4 开发天气应用 27 3.5 小结 40 第4章 移动应用组件 42 4.1 类比HTML 元素与原生组件 42 4.2 处理触摸和手势 ...
尝试使用react-native构建网易新闻客户端中的金币商城
React扩展管理器 (REM)介绍React Extension Manager(或 REM... 运行脚本使用./node_modules/react-extension-manager/rem.sh 要使用 rem,请使用 podfile 和 React Native 扩展初始化一个项目rem (./rem.sh) init 如果
采用react-native构建的一个试验性的feed app
一个React Native项目模板,用于通过分离UI,状态管理和业务逻辑之间的关注点来构建可靠的应用程序。
JdApp是CSDN博客的一个网友发布的个人开源项目,基于facebook的开源项目React Native 实现的一个高仿京东app的项目。作者的博客地址: http://blog.csdn.net/yuanguozhengjust教程一:React Native入门——布局实践:...
go-micro 微服务实战的客户端 === 基于react native 构建 Android iOS app前端
一个使用React Native组件构建的简单产品列表存储,然后将它们共享到bit.dev上的集合中。 带位的React Native-商店演示应用程序一个简单的产品列表商店,由React Native组件构建,然后将它们共享到bit.dev上的集合中...
React Conf 2017 Companion App - 采用React Native构建
用React Native构建的DuckDuckGo App
react-native-renderer, 使用 Angular 和React来构建Android和iOS的应用程序 angular-react-native使用 Angular 和React来构建Android和iOS的应用程序。文档http://angular.github.io/react-native-renderer/插件开
Expo XDE官方版是一款非常优秀的expo开发工具,Expo XDE官方版是一组工具、库和服务,能通过编写JavaScript来构建本地的iOS和Android应用程序,使用起来简单方便!
为React Native构建基于模型的简单表单 目的 在React Native上生成跨平台移动表单字段 跟踪状态和值的能力 用预定义值加载表单 支持嵌套表格和验证 入门 安装 npm i react-native-form0 --save 用法 将表单架构定义...
通过js编写RN界面,使用前端的nodejs的npm工具打包RN开发出来的模块,生成bundle文件,预先存放到原生指定的目录,原生层面在RN引擎初始化时载入并读取bundle并进行渲染
前端开源库-tim-react-nativeTim React Native,一个使用React构建本地应用程序的框架
“留学生React Native计算器作业.zip”是一个为...总的来说,“留学生React Native计算器作业.zip”是一个非常实用的学习资源,可以帮助留学生更好地理解和掌握React Native框架,以及如何使用它来构建移动应用程序。