react-native入門


react-native入門

react native的強大牛逼之處就不扯了,直接進入主題,談談自己初次接觸react native的學習經驗,寫一個簡單的入門文檔,便於總結學習知識,分享學習中遇到和解決的坑,由於我是做android開發的,因此該文主要針對android開發環境進行講解,基於win7系統。

重點參考以下網址和書籍

1. 環境搭建

搭建過程參考“React Native中文網”上的講解,這里詳細說明一下android環境搭架過程。考慮到作為一名android開發人員,androidstudio以及對應的sdk等android開發環境都應該會搭架(或者自己百度android開發環境搭建),默認android環境處於搭建好的狀態。

1.1.三步搞定

  • step1 安裝Node.js
    訪問node.js官網:https://nodejs.org/en/,下載最新的穩定版本,這里我下載的是v4.4.4LTS,下載下來后雙擊安裝即可。
  • step2 安裝react-native
    如果node.js已經安裝好,以及對應的環境變量配置沒有問題,直接運行該語句即可:npm install -g react-native-cli
  • step3 生成react-native開發工程
    react-native init AwesomeProject

    備注:AwesomeProject為你的工程名,自己隨意寫。

1.2.注意事項

  • 由於眾所周知的網絡原因,react-native命令行從npm官方源拖代碼時會遇上麻煩。請將npm倉庫源替換為國內鏡像,否則很有可能step3不能成功,或者耗時過長:
    npm config set registry https://registry.npm.taobao.org
    npm config set disturl https://npm.taobao.org/dist

    react-native init一個工程的時間本來就比較長,請耐性等待(不要過早認為失敗了),我在win7上init大概需要4分鍾左右。

1.3.結束

是的,如果你本身就使用androidstudio進行android應用開發,這只需要這幾步,就完成了react native的開發環境搭建,當然,考慮到斷點調試,你還需要安裝chome瀏覽器以及對應的插件:

2.開發走起

好吧,雖然我們環境已經搭建完成,但是選用一個合適的編輯器還是很重要的,不然敲着代碼都不順心,這里我使用的webstorm,並使用對應的提示插件:https://github.com/virtoolswebplayer/ReactNative-LiveTemplate

2.1.萬事俱備,開始敲代碼

寫一個helloworld實在太簡單,只需要改改之前生成的工程的字符串就搞定了,因此就不寫helloworld了,直接參考《深入淺出 React Native:使用 JavaScript 構建原生應用》這篇文章開始實踐。由於在實踐過程中僅僅只看了這篇文章,沒有看它的源碼,所以覺得自己好坑,讀者遇到問題時,可以嘗試看源碼解決。

  • index,android.js
 
 
 
         
  1. import React, {
  2. AppRegistry,
  3. Component,
  4. Navigator
  5. } from 'react-native';
  6. import SearchPage from './js/SearchPage';
  7. class PropertyFinder extends Component {
  8. render() {
  9. return (
  10. <Navigator
  11. initialRoute={{title: 'SearchPage',component: SearchPage}}
  12. configureScene={(route) => {
  13. return Navigator.SceneConfigs.VerticalDownSwipeJump;
  14. }}
  15. renderScene={(route, navigator) => {
  16. let SearchPage = route.component;
  17. return <SearchPage {...route.params} navigator={navigator} />;
  18. }}/>
  19. );
  20. }
  21. }
  22. AppRegistry.registerComponent('PropertyFinder', () => PropertyFinder);

這里直接使用了es6的最新語法進行編寫,以前沒有怎么寫js代碼,不過感覺這樣的語法結構更容易適應,爽歪歪。

  • 第1行
    import語句后的React導入的react-native模塊中的默認導出內容(export default xxx)。這里特別結實一下,剛開始沒看懂這個語法。
  • 第10行
    如其名字render意思,該函數為該組件的渲染函數,渲染整個組件的顯示。
  • 第25行
    組成入口組件,注意函數的第一個參數名字不能隨便修改,它與android原生代碼中的getMainComponentName保持一致,第二個參數名嘛,只要是一個Component就行了,名字無所謂。

2.2.重點解釋Navigator

Navigator與android系統中的activity棧的作用類似。

  • initialRoute
    它定義了Navigator的初始化組件,該組件將在應用啟動時加載。
  • configureScene
    配置界面與界面之間跳轉時的動畫效果
  • renderScene
    渲染對應的組件

2.3.坑點

第19行的 {…route.params},到目前為止,我還不怎么了解它的原理,僅僅是了解它的作用(ps:剛學習,對jsx理解不深刻),這段代碼定義了一個組件跳轉到另一個組件時,傳遞對象數據的名稱,后續所有的界面跳轉都需要和改名字保持一致,本文使用了params,那么再進行跳轉時,傳遞的參數名必須為params,例如:

 
 
 
         
  1. this.props.navigator.push({
  2. title: 'Results',
  3. component: SearchResults,
  4. params: {listings: response.listings}
  5. });

3.布局

react-native的布局與html與css的思想保持一致,例如:html5使用html標簽描述文檔結構,使用css對文檔表現進行渲染,而react-native使用自己的組件進行界面結構描述,使用類似於css的語法進行界面表示描述。

 
 
 
         
  1. /**
  2. * Created by zjh on 2016/5/5.
  3. */
  4. import React, {
  5. StyleSheet,
  6. Text,
  7. View,
  8. TextInput,
  9. TouchableHighlight,
  10. Image,
  11. ProgressBarAndroid,
  12. Component
  13. } from 'react-native';
  14. import SearchResults from './SearchResults';
  15. class SearchPage extends Component {
  16. // 構造
  17. constructor(props) {
  18. super(props);
  19. // 初始狀態
  20. this.state = {
  21. searchString: 'london',
  22. isLoading: false,
  23. message: ''
  24. };
  25. }
  26. render() {
  27. console.log('SearchPage.render');
  28. var spinner = this.state.isLoading ? (<ProgressBarAndroid styleAttr="Inverse" />) : (<View/>);
  29. return (
  30. <View style={styles.container}>
  31. <Text style={styles.decription}>Search for houses to buy!</Text>
  32. <Text style={styles.decription}>Search by place-name, postcode or search near your location.</Text>
  33. <View style={styles.flowRight}>
  34. <TextInput
  35. style={styles.searchInput}
  36. value={this.state.searchString}
  37. onChangeText={this.onSearchTextChanged.bind(this)}
  38. placeholder='Search via name or postcode'/>
  39. <TouchableHighlight
  40. onPress={this.onSearchPressed.bind(this)}
  41. style={styles.button}>
  42. <Text style={styles.buttonText}>Go</Text>
  43. </TouchableHighlight>
  44. </View>
  45. <TouchableHighlight style={styles.button} onPress={this.onLocationPressed.bind(this)} >
  46. <Text style={styles.buttonText}>Location</Text>
  47. </TouchableHighlight>
  48. <Image source={require('./image/house.png')} />
  49. {spinner}
  50. <Text style={styles.decription}>{this.state.message}</Text>
  51. </View>
  52. );
  53. }
  54. onSearchTextChanged(text) {
  55. console.log('onSearchTextChanged');
  56. this.setState({searchString: text});
  57. console.log(this.state.searchString);
  58. }
  59. _executeQuery(query) {
  60. console.log(query);
  61. this.setState({isLoading: true});
  62. fetch(query)
  63. .then(response => response.json())
  64. .then(json => this._handleResponse(json.response))
  65. .catch(error => this.setState({
  66. isLoading: false,
  67. message: 'Something bad happened: ' + error
  68. }));
  69. }
  70. _handleResponse(response) {
  71. this.setState({isLoading: false, message: ''});
  72. if (response.application_response_code.substr(0, 1) === '1') {
  73. //console.log('Properties found: ' + response.listings.length);
  74. this.props.navigator.push({
  75. title: 'Results',
  76. component: SearchResults,
  77. params: {listings: response.listings}
  78. });
  79. } else {
  80. this.setState({message: 'Location not recognized; please try again.'});
  81. }
  82. }
  83. onSearchPressed() {
  84. console.log('onSearchPressed');
  85. var query = urlForQueryAndPage('place_name', this.state.searchString, 1);
  86. this._executeQuery(query);
  87. }
  88. onLocationPressed() {
  89. navigator.geolocation.getCurrentPosition(
  90. location => {
  91. var search = location.coords.latitude + ',' + location.coords.longitude;
  92. this.setState({searchString: search});
  93. var query = urlForQueryAndPage('centre_point', search, 1);
  94. this._executeQuery(query);
  95. },
  96. error => {
  97. this.setState({
  98. message: 'There was a problem with obtaining your location: ' + error
  99. });
  100. }
  101. );
  102. }
  103. }
  104. function urlForQueryAndPage(key, value, pageNumber) {
  105. var data = {
  106. country: 'uk',
  107. pretty: '1',
  108. encoding: 'json',
  109. listing_type: 'buy',
  110. action: 'search_listings',
  111. page: pageNumber
  112. };
  113. data[key] = value;
  114. var queryString = Object.keys(data)
  115. .map(key => key + '=' + encodeURIComponent(data[key]))
  116. .join('&');
  117. return 'http://api.nestoria.co.uk/api?' + queryString;
  118. }
  119. var styles = StyleSheet.create({
  120. decription: {
  121. marginBottom: 20,
  122. fontSize: 18,
  123. textAlign: 'center',
  124. color: '#656565'
  125. },
  126. container: {
  127. padding: 30,
  128. marginTop: 65,
  129. alignItems: 'center'
  130. },
  131. flowRight: {
  132. flexDirection: 'row',
  133. alignItems: 'center',
  134. alignSelf: 'stretch'
  135. },
  136. buttonText: {
  137. fontSize: 18,
  138. color: 'white',
  139. alignSelf: 'center'
  140. },
  141. button: {
  142. height: 36,
  143. flex: 1,
  144. flexDirection: 'row',
  145. backgroundColor: '#48BBEC',
  146. borderColor: '#48BBEC',
  147. borderWidth: 1,
  148. borderRadius: 8,
  149. marginBottom: 10,
  150. alignSelf: 'stretch',
  151. justifyContent: 'center'
  152. },
  153. searchInput: {
  154. height: 36,
  155. padding: 4,
  156. marginRight: 5,
  157. flex: 4,
  158. fontSize: 18,
  159. borderWidth: 1,
  160. borderColor: '#48BBEC',
  161. borderRadius: 8,
  162. color: '#48BBEC'
  163. },
  164. image: {
  165. width: 217,
  166. height: 138
  167. }
  168. });
  169. export default SearchPage;

3.1.常用布局組件與渲染熟悉

react-native提供了大量的組件,例如VIew、Text、Image等等,詳細的使用方法,請參考《React Native中文網》中的內容。

3.2.坑點

雖然這里的界面渲染語法與css保持一致,比較react-native不是運行在瀏覽器上,因此它支持的也僅僅是一個子集而已。

  • flex
    該屬性,在進行多設備界面適配時,會使用得很多,我遇到一個坑,沒有設置父組件為alignSelf: ‘stretch’,導致子組件雖然設置了alignSelf: ‘stretch’和對應的flex值,但是卻沒有按照比例正常顯示的情況。

4.全文結束

是的,在這里就結束了,掌握的知識不多,入門確實也就是這么簡單。






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM