ReactNavtive框架教程(4)

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

 注意:所有圖片放在了百度相冊空間。假設你看不到圖片。請複製圖片URL,而後粘貼到地址欄中進行查看。html


開始搜索html5

爲了實現搜索概念,咱們需要處理Gobutton點擊事件,建立相應的API請求,顯示網絡請求的狀態。java

打開SearchPage.js, 在constructor方法中改動state的初始化代碼:react

this.state = {es6

  searchString: 'london',json

  isLoading: falsereact-native

};api

isLoading 屬性用於表示查詢是否正在進行。promise

在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類,所以被定義爲函數而不是方法。它首先將key\value參數以鍵值對形式放到了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 ,進行一個查找動做。

你將看到搜索結果例如如下:

相關文章
相關標籤/搜索