原文: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 ,進行一個查找動做。
你將看到搜索結果例如如下: