跟我学用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';

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’ 按钮返回到根页面。

c23812701c4ff54163cf2978e28ebb50_b

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

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

发表回复