React Native 開發(fā)已經(jīng)初見(jiàn)端倪, 可以完成最基本的功能. 通過(guò)開發(fā)一些簡(jiǎn)單的應(yīng)用, 可以更加熟練的掌握 RN 的知識(shí). 本文介紹非常簡(jiǎn)單的一款房產(chǎn)搜索的App, 通過(guò)調(diào)用公開的搜索服務(wù), 把網(wǎng)絡(luò)的數(shù)據(jù)展示在應(yīng)用中. 通過(guò)代碼更多的了解 RN 的特性.

已經(jīng)實(shí)現(xiàn) iOS 版本, 僅供學(xué)習(xí)和參考, 可以直接運(yùn)行, 但是 RN 變化較快, 可能不兼容. 關(guān)于在運(yùn)行項(xiàng)目中可能出現(xiàn)的問(wèn)題, 請(qǐng)參考.
主要內(nèi)容:
- 使用Navigator棧跳轉(zhuǎn)頁(yè)面.
- 使用fetch請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù).
- 使用ListView展示列表數(shù)據(jù).
本文源碼的GitHub下載地址
配置項(xiàng)目
初始化 React Native 的項(xiàng)目.
react-native init WclPropertyFinder
修改 Android 的 Gradle 構(gòu)建版本.
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
}
運(yùn)行 iOS 和 Android 項(xiàng)目.
調(diào)試: iOS 模擬機(jī),
Cmd + R重新加載,Cmd + D模擬晃動(dòng); Android, 晃動(dòng)手機(jī).
修改index.ios.js的內(nèi)容, 設(shè)置啟動(dòng)模塊. 使用NavigatorIOS加載組件搜索頁(yè)SearchPage.
// 使用Navigator管理組件, 注意: 不要糾結(jié)于跨平臺(tái), 學(xué)習(xí)為主
class WclPropertyFinderApp extends React.Component {
render() {
return (
<React.NavigatorIOS
style={styles.container}
initialRoute={{
title: '搜房產(chǎn)',
component: SearchPage,
}}/>
);
}
}
注冊(cè)組件WclPropertyFinderApp至應(yīng)用WclPropertyFinder.
React.AppRegistry.registerComponent('WclPropertyFinder', () => WclPropertyFinderApp);
首頁(yè)搜索
搜索頁(yè)(SearchPage)包含一個(gè)搜索庫(kù), 可以使用地址或郵編搜索英國(guó)的房產(chǎn)信息.
通過(guò)輸入框的參數(shù)創(chuàng)建網(wǎng)絡(luò)請(qǐng)求URL, 并把請(qǐng)求發(fā)送出去, 獲取信息.
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;
}
在獲取網(wǎng)絡(luò)請(qǐng)求URL后, 使用fetch函數(shù)獲取數(shù)據(jù).
_executeQuery(query) {
console.log(query);
this.setState({isLoading: true});
// 網(wǎng)絡(luò)請(qǐng)求
fetch(query)
.then(response => response.json())
.then(json => this._handleResponse(json.response))
.catch(error => this.setState({
isLoading: false,
message: 'Something bad happened ' + error
}));
}
處理返回的Json數(shù)據(jù), 使用Navigator跳轉(zhuǎn)到搜索結(jié)果SearchResults頁(yè)面.
_handleResponse(response) {
this.setState({isLoading: false, message: ''});
if (response.application_response_code.substr(0, 1) === '1') {
console.log('Properties found: ' + response.listings.length);
// 使用listings調(diào)用結(jié)果頁(yè)面SearchResults
this.props.navigator.push({
title: '搜索結(jié)果',
component: SearchResults,
passProps: {listings: response.listings}
});
} else {
this.setState({message: 'Location not recognized; please try again.'});
}
}
搜索結(jié)果
把獲取的房產(chǎn)信息, 逐行渲染并顯示于ListView中.
renderRow(rowData, sectionID, rowID) {
var price = rowData.price_formatted.split(' ')[0];
return (
<TouchableHighlight
onPress={()=>this.rowPressed(rowData.guid)}
underlayColor='#dddddd'>
// 布局...
</TouchableHighlight>
);
}
ListView設(shè)置數(shù)據(jù)源dataSource, 每行渲染renderRow.
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
/>
);
}
點(diǎn)擊ListView的行, 可以跳轉(zhuǎn)至房產(chǎn)信息頁(yè)面.
rowPressed(propertyGuid) {
var property = this.props.listings.filter(prop => prop.guid === propertyGuid)[0];
this.props.navigator.push({
title: '房產(chǎn)信息',
component: PropertyView,
passProps: {property: property}
});
}
房產(chǎn)信息
房產(chǎn)信息是單純顯示頁(yè)面, 顯示圖片和文字內(nèi)容.
class PropertyView extends Component {
render() {
var property = this.props.property; // 由SearchResult傳遞的搜索結(jié)果
var stats = property.bedroom_number + ' bed ' + property.property_type;
if (property.bathroom_number) {
stats += ', ' + property.bathroom_number + ' ' +
(property.bathroom_number > 1 ? 'bathrooms' : 'bathroom');
}
var price = property.price_formatted.split(' ')[0];
return (
// 布局...
);
}
}
最終效果

使用 RN 開發(fā)應(yīng)用非??旖? 復(fù)用邏輯到多個(gè)平臺(tái), 節(jié)省開發(fā)成本, 不過(guò)目前正在完善中.
本文參考我的朋友Tom的一篇文章.
OK, that's all! Enjoy it!