ReactNavtive框架教程(4)

原文:http://www.raywenderlich.com/99473/introducing-react-native-building-apps-javascript

 注意:全部图片放在了百度相冊空间。假设你看不到图片。请复制图片URL,然后粘贴到地址栏中进行查看。


開始搜索

为了实现搜索概念,我们须要处理Gobutton点击事件,创建相应的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}

在Gobutton相应的 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类没有訪问器。因此也就没有私有的概念。因此我们会在方法名前加一个下划线。以表示该方法视同为私有方法。

当Gobutton被点击。 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类,因此被定义为函数而不是方法。它首先将keyvalue參数以键值对形式放到了data集合中,然后将data集合转换成以&符分隔的“键=值”形式。=>语法是箭头函数的写法,一种创建匿名函数简洁写法。详细请參考

recentaddition to the JavaScript language 。

回到模拟器,按下 Cmd+R 重新启动App,然后点击‘Go’ button。你将看到网络指示器開始转动。

同一时候控制台将输出:


网络指示器显示,同一时候要请求的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堆栈中,同一时候你的导航栏上将出现一个Backbutton。点击它能够返回到上一页面。

回到模拟器, 按下Cmd+R ,进行一个查找动作。

你将看到搜索结果例如以下:



原文地址:https://www.cnblogs.com/liguangsunls/p/6979140.html