React Native 簡單入門 二

React Native介紹

React Native 是Facebook開源的一個跨平臺移動應(yīng)用開發(fā)框架。直白點(diǎn)說,借助React Native你可以直接使用JS來開發(fā)原生移動應(yīng)用。

React和React Native

React也是Facebook開源的一個框架,一個JS UI 框架,React Native 是以React為一部分基礎(chǔ)的衍生產(chǎn)品。也就是說,除了JavaScript,你還需要熟悉一下React這個UI框架,以便于更好的上手React Native。

安裝

使用React Native開發(fā)原生APP時,除了JS的Node環(huán)境,還是需要配置好相關(guān)的原生開發(fā)環(huán)境。Android的JDK和Android Studio,IOS的XCODE,當(dāng)然一般還會裝一些輔助的工具,這里就不詳細(xì)說明了,React Native中文網(wǎng)上有詳細(xì)的開發(fā)環(huán)境搭建說明文檔。

第一個RN應(yīng)用

搭建好開發(fā)環(huán)境后,我們就可以使用RN開發(fā)原生APP了。在cmd中鍵入下列命令就可以生成一個RN的helloworld項目,并在android機(jī)器上運(yùn)行起來

react-native init AwesomeProject
cd AwesomeProject
react-native run-android

運(yùn)行起來后就是下面的界面

image

可以看到界面中也給了我們相應(yīng)的提示,打開工程根目錄中的App.js文件

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View
} from 'react-native';

const instructions = Platform.select({
  ios: 'Press Cmd+R to reload,\n' +
    'Cmd+D or shake for dev menu',
  android: 'Double tap R on your keyboard to reload,\n' +
    'Shake or press menu button for dev menu',
});

export default class App extends Component<{}> {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit App.js
        </Text>
        <Text style={styles.instructions}>
          {instructions}
        </Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

修改render()方法中的返回

render() {
        return (
            <View style={styles.container}>
              <Text style={styles.welcome}>
                Hello React Native!
              </Text>
            </View>
        );
    }

然后選中模擬器雙擊鍵盤R,就更新界面了。

image

我們還可以使用Ctrl+M呼出開發(fā)者菜單,真機(jī)的話,搖一搖即可。
image

上圖的菜單先簡單介紹幾個,Reload就是加載資源即為刷新,Enable Hot Reload為熱加載,開啟此選項,開發(fā)時代碼變動,界面自動刷新。以后除非原生代碼改動,可以使用npm start快速開啟調(diào)試服務(wù),不需要每次都運(yùn)行react-native run-android
然后再回過頭看下App.js的代碼,可以發(fā)現(xiàn)React Native基本跟React是差不多的,只不過基礎(chǔ)組件不是web組件而是原生組件。這里先列出RN的基礎(chǔ)組件

  • AccessibilityInfo
  • ActivityIndicator
  • Button
  • CheckBox
  • DatePickerIOS
  • DrawerLayoutAndroid
  • FlatList
  • Image
  • KeyboardAvoidingView
  • ListView
  • ListView.DataSource
  • Modal
  • NavigatorIOS
  • Picker
  • PickerIOS
  • ProgressBarAndroid
  • ProgressViewIOS
  • RefreshControl
  • ScrollView
  • SectionList
  • SegmentedControlIOS
  • Slider
  • StatusBar
  • Switch
  • TabBarIOS
  • TabBarIOS.Item
  • Text
  • TextInput
  • ToolbarAndroid
  • TouchableHighlight
  • TouchableNativeFeedback
  • TouchableOpacity
  • TouchableWithoutFeedback
  • View
  • ViewPagerAndroid
  • VirtualizedList
  • WebView

使用基礎(chǔ)組件時先從react-native包中導(dǎo)入,比如我們使用Button時,先添加導(dǎo)入

import {
    Button
} from 'react-native';

然后在reder方法中返回

render() {
        return (
            <View style={styles.container}>
              <Button title={'hello rn'} onPress={()=>{
                alert('hello rn')
              }}/>
            </View>
        );
    }

各組件的使用可以閱讀官方或中文網(wǎng)文檔,有詳細(xì)介紹。這里補(bǔ)充一些React的相關(guān)知識。前面的代碼就有兩個React的基礎(chǔ)概念,Component組件和JSX語法,Component組件是React中很重要的一個概念,React組件使用render方法接收數(shù)據(jù)并輸出JSX展示。上面代碼中類似xml的寫法就稱為JSX,是react對js的一種語法擴(kuò)展。JSX與xml語法類似,可以定義屬性和子元素,不同的是通過{}來加入js表達(dá)式。接觸過angularvue的同學(xué)應(yīng)該對這種寫法會比較熟悉。再說明一點(diǎn),JSX也是一種表達(dá)式,在編譯以后也會轉(zhuǎn)換成普通的js對象。也就說你可以像下面這么用

let text = <Text>hello rn</Text>

if(isAndroid)
{
    return <Text>hello android</Text>
}else
{
    return <Text>hello ios</Text>
}

let  txts = [];
txts.push(<Text>hello rn</Text>);

關(guān)于Component組件還有兩個重要概念,props(屬性)和state(狀態(tài)),在組件內(nèi)我們通過props來訪問傳入的數(shù)據(jù),比如說我們之前使用的button組件

<Button title={'hello rn'}/>

Button類中,就可以通過props訪問到

class MyButton extends Component{
    render ()
    {
        let title =this.props.title
        ...
    }
}

state是用來保持組件內(nèi)部狀態(tài)的,當(dāng)state改變時,組件會重新調(diào)用render()方法,刷新組件UI。

class MyButton extends Component{
    constructor(props){
        super(props);
        this.state={
            title:props.title
        }
    }
    onClick(){
        this.setState({title:'isClicked'})
    }
}

constructor()構(gòu)造方法中賦值,使用this.setState()方法更新state。

布局和樣式

所有的基礎(chǔ)組件都接收一個style屬性,接收一個對象或數(shù)組,組件的寬高背景等等都是通過這個屬性來定制的

<View style={{
                    height:100,
                    width:100,
                    backgroundColor:'red'
                }}>
                    ...
</View>

使用的樣式名基本都遵循了web上的css命名,只是按照J(rèn)S的語法規(guī)范使用了駝峰命名法,列如background-color改為backgroundColor,而且給寬高設(shè)置的尺寸都是沒有單位的,表示與設(shè)備像素?zé)o關(guān)的邏輯像素點(diǎn)。補(bǔ)充說明一下單位轉(zhuǎn)換和尺寸適配的問題,單位方面,一般現(xiàn)在UI會給我們PxCook的源文件,Android的話,對照相應(yīng)密度的dp大小設(shè)置即可。IOS,對照相應(yīng)倍圖的pt大小設(shè)置即可。屏幕尺寸方面,因為布局采用的是flexBox,所以對不同的屏幕尺寸基本上能提供一致的布局結(jié)構(gòu)。其他更細(xì)節(jié)的適配需求,現(xiàn)在并沒有系統(tǒng)整理,以后再和大家分享交流。
然后再說下FlexBox布局,RN中的FlexBox布局和Web上的CSS基本一致,但有兩點(diǎn)差異,flexDirection的默認(rèn)值是column而不是row,而flex也只能指定一個數(shù)字值。在平常開發(fā)的時候,使用flexDirection、alignItemsjustifyContent三個樣式屬性就已經(jīng)能滿足大多數(shù)布局需求,使用flexDirection決定布局的主軸,justifyContent決定子元素在主軸上的位置,alignItems決定子元素在次軸上的位置。舉個栗子吧,這樣比較形象一點(diǎn),比如下圖所示的界面

image

圖中卡片布局的大致實(shí)現(xiàn)代碼如下

            <View style={{alignItems:'center',justifyContent:'center',minHeight:100...}}>
                <Text style={{color:'white'...}}>
                    昨日票房 2017年11月7日
                </Text>
                <View style={{flexDirection:'row',alignItems:'center',marginTop:20...}>
                    <Text style={{color:'white',fontSize:24...}}>
                        701786
                    </Text>
                    <Text style={{color:'white',marginTop:10}}>
                        萬
                    </Text>
                </View>
                <Text style={{color:'white',,marginTop:20...}}>
                    每日0點(diǎn)更新票房
                </Text>
            </View>

上面的代碼只是大概布局思路,當(dāng)然這個卡片的真正實(shí)現(xiàn)還用到了LinearGradient控件和ImageBackground控件。

頁面跳轉(zhuǎn)

我們一般使用React Navigation來構(gòu)建多頁面以及跳轉(zhuǎn)頁面,使用前要先安裝

yarn add react-navigation

然后在app.js(如果你沒改動index.js中的app組件注冊的話)注冊頁面

import { StackNavigator } from 'react-navigation';
import Main from "./pages/main";
import NationwideDetail from "./pages/cinema/nationwideDetail";
import Cinema from "./pages/cinema/cinemaIndex";
import DatePickerPage from "./pages/common/datePickerPage";
import ForecastDetail from "./pages/cinema/forecastDetail";
import CinemaDetail from "./pages/cinema/cinemaDetail";

const RootNavigator = StackNavigator({
    NationwideDetail:{
      screen:NationwideDetail,
    },
    Cinema:{
        screen:Cinema
    },
    DatePickerPage:{
      screen:DatePickerPage
    },
    ForecastDetail:{
        screen:ForecastDetail
    },
    CinemaDetail:{
        screen:CinemaDetail
    }
});
export default RootNavigator;

最初顯示第一個注冊頁面,注冊完成之后,每個頁面中的props屬性可以獲得navigation對象,通過navigation對象進(jìn)行頁面跳轉(zhuǎn)

this.props.navigation.navigate('NationwideDetail')

也可以攜帶參數(shù)

this.props.navigation.navigate('NationwideDetail',{name:'wuHuaRong'})

參數(shù)在navigation.state.params.name中獲取。

返回頁面

我們還可以通過navigation.goBack()方法關(guān)閉當(dāng)前頁面返回上個頁面,navigation.goBack('NationwideDetail')可以指定回到某個頁面。如果還想關(guān)閉頁面時返回某個值,類似android中的startActivityForResult,需要再集成redux狀態(tài)機(jī)來管理多個頁面之間的共享狀態(tài)。此部分,先不詳細(xì)說明了。

網(wǎng)絡(luò)請求

RN提供了與web一致的Fetch API,也允許使用XMLHttpRequest API,以及基于XMLHttpRequest的第三方庫frisbee或是axios,此部分文檔有詳細(xì)說明就不再贅訴了。

觸摸

簡單的點(diǎn)擊和長按事件可以使用官方提供的四個Touchable控件,TouchableHighlightTouchableNativeFeedbackTouchableOpacityTouchableWithoutFeedback

<TouchableHighlight onPress={this._onPressButton} onLongPress={this._onLongPressButton}>
        <Text>Button</Text>
</TouchableHighlight>

上下左右滑動可以使用ScrollView組件,復(fù)雜的手勢請參考PanResponderAPI

異步問題

因為RN中只有一個JS執(zhí)行線程,是不能直接開啟一個異步線程的來執(zhí)行耗時操作的,但是可以使用InteractionManager來保障UI的渲染性能的。

InteractionManager.runAfterInteractions(() => {
   // ...需要長時間同步執(zhí)行的任務(wù)...
});

資源引用

使用require方法來引用項目中的靜態(tài)資源,如.png,.mp3,.wav,mp4,.mov,.html.pdf
比如Image控件的使用

<Image source={require('./my-icon.png')} />
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,065評論 25 708
  • 簡短說明 收錄一些好用的RN第三方組件,以方便日常的使用,大家有什么推薦的也可以跟我說,我加進(jìn)去。如有冒犯,可以聯(lián)...
    以德扶人閱讀 43,709評論 44 214
  • 最近在學(xué)習(xí)ReactNative開發(fā),感覺還是很容易上手的,搜集了不少資料,分享給大家。 為什么選ReactNat...
    StChris閱讀 1,647評論 0 37
  • 昨晚做了個夢,我一個人走在路上,四周天氣昏暗,濃霧重重。我也不知道自己要去哪,就徑直朝前面走著,走著,突然前面出現(xiàn)...
    子悠說財閱讀 326評論 0 2
  • 蝸牛身上背著重重的殼。相較于它們平均10厘米的身體長度而言。這只殼幾乎掩蓋了它們身體百分之八十的面積。除...
    歌齡閱讀 386評論 6 4