标签:
原文:http://www.raywenderlich.com/99473/introducing-react-native-building-apps-javascript
注意:所有图片放在了百度相册空间,如果你看不到图片,请复制图片URL,然后粘贴到地址栏中进行查看。
开始搜索
为了实现搜索概念,我们需要处理Go按钮点击事件,创建对应的API请求,显示网络请求的状态。
打开SearchPage.js, 在constructor方法中修改state的初始化代码:
this.state = { searchString: ‘london‘, isLoading: false }; |
isLoading 属性用于表示查询是否正在进行。
在render方法最上面增加:
var spinner = this.state.isLoading ? ( <ActivityIndicatorIOS hidden=‘true‘ size=‘large‘/> ) : ( <View/>); |
用了一个三目运算,这是一个if语句的简单形式。如果isLoading为true,显示一个网络指示器,否则显示一个空的view。
在return语句中,在Image下增加:
{spinner} |
在Go按钮对应的 TouchableHighlight 标签中增加如下属性:
onPress={this.onSearchPressed.bind(this)} |
在 SearchPage 类中新增如下方法:
_executeQuery(query) { console.log(query); this.setState({ isLoading: true }); }
onSearchPressed() { var query = urlForQueryAndPage(‘place_name‘, this.state.searchString, 1); this._executeQuery(query); } |
_executeQuery() 目前仅仅是在控制台中输出一些信息,同时设置isLoading属性为true,剩下的功能我们留到后面完成。
注意: JavaScript类没有访问器,因此也就没有私有的概念。因此我们会在方法名前加一个下划线,以表示该方法视同为私有方法。
当Go按钮被点击, onSearchPressed() 即被调用。
在 SearchPage 类声明之前,声明如下实用函数:
function urlForQueryAndPage(key, value, pageNumber) { var data = { country: ‘uk‘, pretty: ‘1‘, encoding: ‘json‘, listing_type: ‘buy‘, action: ‘search_listings‘, page: pageNumber }; data[key] = value;
var querystring = Object.keys(data) .map(key => key + ‘=‘ + encodeURIComponent(data[key])) .join(‘&‘);
return ‘http://api.nestoria.co.uk/api?‘ + querystring; }; |
这个函数不依赖SearchPage类,因此被定义为函数而不是方法。它首先将key\value参数以键值对形式放到了data集合中,然后将data集合转换成以&符分隔的“键=值”形式。=>语法是箭头函数的写法,一种创建匿名函数简洁写法,具体请参考
recentaddition to the JavaScript language 。
回到模拟器,按下 Cmd+R 重启App,然后点击‘Go’ 按钮。你将看到网络指示器开始转动。同时控制台将输出:
网络指示器显示,同时要请求的URL也打印出来了。拷贝并粘贴URL到Safari,查看搜索结果。你将看到一堆JSON对象。我们将用代码解析这些JSON对象。
注意: 这个App使用 Nestoria API 来查找房子。查找结果以JSON格式返回。官方文档中列出了所有请求的URL规范及响应格式。
发送请求
打开 SearchPage.js,在初始化状态过程中增加一个message属性:
this.state = { searchString: ‘london‘, isLoading: false, message: ‘‘ }; |
在render方法中,在UI元素的最后加入:
<Text style={styles.description}>{this.state.message}</Text> |
这个Text用于向用户显示一些文本。
在 SearchPage 类中,在 _executeQuery()方法最后加入:
fetch(query) .then(response => response.json()) .then(json => this._handleResponse(json.response)) .catch(error => this.setState({ isLoading: false, message: ‘Something bad happened ‘ + error })); |
fetch 函数在 Fetch API中定义,这个新的JavaScript规范被Firefox 39(Nightly版)以及Chrome 42(开发版)支持,它在XMLHttpRequest的基础上进行了极大的改进。结果是异步返回的,同时使用了 promise规范,如果response中包含有效的JSON对象则将JSON对象的response成员(另一个JSON)传到_handleResponse方法(后面实现)。
然后在 SearchPage类中增加方法:
_handleResponse(response) { this.setState({ isLoading: false , message: ‘‘ }); if (response.application_response_code.substr(0, 1) === ‘1‘) { console.log(‘Properties found: ‘ + response.listings.length); } else { this.setState({ message: ‘Location not recognized; please try again.‘}); } } |
如果查询结果成功返回,我们重置 isLoading 属性为false,然后打印结果集的总数。
注意: Nestoria有 不以1开头的响应码, 这些代码都非常有用。例如202 和 200表示返回一个推荐位置的列表。当完成这个实例后,你可以尝试处理这些返回码,并将列表提供给用户选择。
保存,返回模拟器,按下Cmd+R ,然后搜索 ‘london’你将在控制台看到一条消息,表示搜索到20条房子信息。尝试输入一个不存在的地名,比如 ‘narnia’ 你将看到如下信息:
展现搜索结果
新建一个文件: SearchResults.js, 编写如下代码:
‘use strict‘;
var React = require(‘react-native‘); var { StyleSheet, Image, View, TouchableHighlight, ListView, Text, Component } = React; |
一条requires语句和一个结构赋值。
定义一个Componet子类:
class SearchResults extends Component {
constructor(props) { super(props); var dataSource = new ListView.DataSource( {rowHasChanged: (r1, r2) => r1.guid !== r2.guid}); this.state = { dataSource: dataSource.cloneWithRows(this.props.listings) }; }
renderRow(rowData, sectionID, rowID) { return ( <TouchableHighlight underlayColor=‘#dddddd‘> <View> <Text>{rowData.title}</Text> </View> </TouchableHighlight> ); }
render() { return ( <ListView dataSource={this.state.dataSource} renderRow={this.renderRow.bind(this)}/> ); }
} |
上述代码中使用了一个专门的组件——ListView ——该组件非常像ITableView。通过ListView.DataSource, 我们可以向ListView提供数据。renderRow函数则用于为每个行提供UI。
在构建数据源的时候,我们使用箭头函数对不同的行进行识别。这个函数在ListView进行“一致化”的时候被调用,以便判断列表中的数据是否被改变。在本例中,NestoriaAPI有一个guid属性,刚好可以用来作为判断的标准。
最后,加入一条模块输出语句:
module.exports = SearchResults; |
SearchPage.js 头部,require 下方加入:
var SearchResults = require(‘./SearchResults‘); |
这样我们就可以 SearchPage 类中使用SearchResults类了。
在_handleResponse 方法,将console.log 一句替换为:
this.props.navigator.push({ title: ‘Results‘, component: SearchResults, passProps: {listings: response.listings} }); |
上述代码将导航至SearchResults 页面,并将请求到的列表数据传递给它。Push方法可以将页面添加到导航控制器的ViewController堆栈中,同时你的导航栏上将出现一个Back按钮,点击它可以返回到上一页面。
回到模拟器, 按下Cmd+R ,进行一个查找动作。你将看到搜索结果如下:
标签:
原文地址:http://blog.csdn.net/kmyhy/article/details/46953355