本文案例、代码及主要内容基于知乎前端专栏翻译的文章《深入浅出React Native:使用JavaScript构建原生应用》《Introducing React Native: Building Apps with JavaScript》而写。
在原文的基础上做了一些校对,并增加了android得环境安装和调试的内容。
由我书写的注释将会显示左边这个紫色竖线(#523f6d),而原文的注释为蓝色的(#559bce)。
内容传送门
一、《深入浅出R跟我学用React Native构建原生应用(一)
二、《深入浅出R跟我学用React Native构建原生应用(二)
三、《深入浅出R跟我学用React Native构建原生应用(三)
四、《深入浅出R跟我学用React Native构建原生应用(四)
五、《深入浅出R跟我学用React Native构建原生应用(五)
六、《深入浅出R跟我学用React Native构建原生应用(六)
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:kmokidd
链接:http://zhuanlan.zhihu.com/FrontendMagazine/19996445
来源:知乎
执行 API 请求
还是 SearchPage.js 文件中,更新构造器中的初始 state 添加一个message 变量:
this.state = {
searchString: 'london',
isLoading: false,
message: ''
};
在 render 内部,将下面的代码添加到 UI 的底部:
<Text style={styles.description}>{this.state.message}</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 函数,它是 Web API 的一部分。和 XMLHttpRequest 相比,它提供了更加先进的 API。异步响应会返回一个 promise,成功的话会转化 JSON 并且为它提供了一个你将要添加的方法。
最后一步是将下面的函数添加到 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.'});
}
}
如果查询成功,这个方法会清除掉正在加载标识并且记录下查询到属性的个数。
注意:Nestoria 有很多种返回码具备潜在的用途。比如,202 和 200 会返回最佳位置列表。当你创建完一个应用,为什么不处理一下这些,可以为用户呈现一个可选列表。
保存项目,然后在模拟器中按下 Cmd+R,尝试搜索 ‘london’;你会在日志信息中看到 20 properties were found。然后随便尝试搜索一个不存在的位置,比如 ‘narnia’,你会得到下面的问候语。
是时候看一下这20个房屋所对应的真实的地方,比如伦敦!
结果显示
创建一个新的文件,命名为 SearchResults.js,然后加上下面这段代码:
'use strict';
var React = require('react-native');
var {
StyleSheet,
Image,
View,
TouchableHighlight,
ListView,
Text,
Component
} = React;
你肯定注意到啦,这里用到了 require 语句将 react-native 模块引入其中,还有一个重构赋值语句。
接着就是加入搜索结果的组件:
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 – 它能将数据一行行地呈现出来,并放置在一个可滚动的容器内,和 UITableView 很相似。通过 ListView.DataSource 将 ListView 的数据引入,还有一个函数来显示每一行UI。
在构建数据源的同时,你还需要一个函数用来比较每两行之间是否重复。 为了确认列表数据的变化,在 reconciliation 过程中ListView 就会使用到这个函数。在这个实例中,由 Nestoria API 返回的房屋数据都有一个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方法确保搜索结果全部推进导航栈中,这样你就可以通过 ‘Back’ 按钮返回到根页面。
回到模拟器,按下 Cmd+R 刷新页面,然后试试看我们的搜索。估计你会得到类似下面这样的结果:
耶!你的搜索实现了呢,不过这搜索结果页面的颜值也太低了,不要担心,接下来给它化化妆。