跟我学用REACT NATIVE构建原生应用(四)

本文案例、代码及主要内容基于知乎前端专栏翻译的文章《深入浅出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’,你会得到下面的问候语。

3a4a28712b2169f7eea6dad169b2168e_b

是时候看一下这20个房屋所对应的真实的地方,比如伦敦!

结果显示

创建一个新的文件,命名为 SearchResults.js,然后加上下面这段代码:

"use strict";

你肯定注意到啦,这里用到了 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’ 按钮返回到根页面。

c23812701c4ff54163cf2978e28ebb50_b

回到模拟器,按下 Cmd+R 刷新页面,然后试试看我们的搜索。估计你会得到类似下面这样的结果:

耶!你的搜索实现了呢,不过这搜索结果页面的颜值也太低了,不要担心,接下来给它化化妆。

Comments