ReactNative從零到完整項(xiàng)目-如何使用導(dǎo)航器跳轉(zhuǎn)頁(yè)面

項(xiàng)目連接: 93Laer/MyDemo
ReactNative使用手冊(cè)

關(guān)鍵詞:
  • 場(chǎng)景(Scene):可簡(jiǎn)單的理解為一個(gè)界面中所有的組件構(gòu)成了這個(gè)界面,其實(shí)就是構(gòu)成了一個(gè)場(chǎng)景(Scene)
  • Navigator:官方推薦的一個(gè)純JavaScript實(shí)現(xiàn)了一個(gè)導(dǎo)航棧,因此可以跨平臺(tái)工作,同時(shí)也便于定制的一個(gè)導(dǎo)航器。
    Scene官方實(shí)例:
import React, { Component } from 'react';
import { View, Text } from 'react-native';

export default class MyScene extends Component {
  static defaultProps = {
    title: 'MyScene'
  };

  render() {
    return (
      <View>
        <Text>Hi! My name is {this.props.title}.</Text>
      </View>
    )
  }
}

這就構(gòu)成了一個(gè)scene,感覺(jué)相當(dāng)于沒(méi)解釋,但是為了再一次練習(xí)props,在項(xiàng)目中我還是再寫(xiě)了一次

使用Navigator:這里就不寫(xiě)了,按照官方的實(shí)例跑一次發(fā)現(xiàn)報(bào)錯(cuò),報(bào)在'react-native'modules中找不到Navigator這個(gè)組件了,也提示了處理方法,但是我再看看官方文檔發(fā)現(xiàn)其實(shí)現(xiàn)在官方推薦的事是Navigator的教程,所以接下來(lái)直接進(jìn)入react-navigation庫(kù)學(xué)習(xí)

image.png

react-navigation庫(kù)使用:

安裝module:npm install --save react-navigation
最簡(jiǎn)單使用(直接使用StackNavigator加載界面)

/**
 * 創(chuàng)建人:賴天兵
 * 時(shí)間: 2018/2/24
 * 簡(jiǎn)書(shū):http://www.itdecent.cn/u/2229fd214880
 * 掘金:https://juejin.im/user/58647e21128fe1006d0f3f3e
 * github:https://github.com/93Laer
 * 描述:
 */
import { View, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';
import React from 'react';
class NavigatorTest extends React.Component {
    render() {
        return (
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Home Screen</Text>
            </View>
        )
    }
}

export default StackNavigator({
    AppHome: {screen: NavigatorTest}
});

注意:

  • 1、 路由名稱的大小寫(xiě)無(wú)關(guān)緊要,您可以使用小寫(xiě)字母home或大寫(xiě)字母Home,這取決于您。我們更喜歡大寫(xiě)我們的路線名稱。
  • 2、screen組件唯一需要的配置是組件。您可以閱讀關(guān)于StackNavigator參考中可用的其他選項(xiàng)的更多信息。
  • 3、在React Native中,從其中導(dǎo)出的組件App.js是您的應(yīng)用程序的入口點(diǎn)(或根組件) - 它是每個(gè)其他組件從中下降的組件。在你的應(yīng)用的根目錄下對(duì)組件進(jìn)行更多的控制通常比導(dǎo)出一個(gè)更有用StackNavigator,所以讓我們導(dǎo)出一個(gè)只呈現(xiàn)我們的組件StackNavigator(其實(shí)簡(jiǎn)單講就是在APP入口的時(shí)候就使用StackNavigator組件)。
效果圖

在StackNavigator中添加多條線路(注冊(cè)多個(gè)組件):也很簡(jiǎn)單,就直接上代碼解釋重點(diǎn)了

/**
 * 創(chuàng)建人:賴天兵
 * 時(shí)間: 2018/2/24
 * 簡(jiǎn)書(shū):http://www.itdecent.cn/u/2229fd214880
 * 掘金:https://juejin.im/user/58647e21128fe1006d0f3f3e
 * github:https://github.com/93Laer
 * 描述:
 */
import React from 'react';
import { View, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen  extends React.Component {
    render() {
        return (
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Home Screen</Text>
            </View>
        )
    }
}
class DetailsScreen  extends React.Component {
    render() {
        return (
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Details Screen</Text>
            </View>
        );
    }
}
export default StackNavigator({
        //todo 1、直接展示
        //AppHome: {screen: HomeScreen}


        //todo 2、初始化多條線路,通過(guò)initialRouteName控制初始化那一個(gè)路由
        Home: {
            screen: HomeScreen,
        },
        Details: {
            screen: DetailsScreen,
        },
    },
    {
        //通過(guò)initialRouteName來(lái)控制初始化哪一個(gè)路由
        initialRouteName: 'Home',
    }
);

解釋:其實(shí)就是在堆棧中多初始化了幾條線路,然后通過(guò)initialRouteName來(lái)控制來(lái)展示那一條。

實(shí)現(xiàn)跳轉(zhuǎn)

問(wèn)題一:我們?cè)趺磸闹髀肪€(HomeScreen)移動(dòng)到細(xì)節(jié)(DetailsScreen)路線?

接下來(lái)我們將HomeScreen修改一下,實(shí)現(xiàn)點(diǎn)擊按鈕跳轉(zhuǎn)詳情頁(yè)的功能,代碼如下:
class HomeScreen  extends React.Component {
    render() {
        return (
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Home Screen</Text>
                <Button
                    title="Go to Details"
                    //這里跳轉(zhuǎn)的頁(yè)面是我們已經(jīng)在StackNavigator中注冊(cè)了的,如果是沒(méi)注冊(cè)又會(huì)發(fā)生什么呢
                    onPress={() => this.props.navigation.navigate('Details')}
                    />
            </View>
        )
    }
}
效果

問(wèn)題二:當(dāng)我們跳轉(zhuǎn)一個(gè)我們未在StackNavigator中注冊(cè)的界面又會(huì)發(fā)生什么呢?
我們直接將跳轉(zhuǎn)代碼改成onPress={() => this.props.navigation.navigate('XXX')},看看會(huì)怎樣,結(jié)果就不展示了,其實(shí)就是沒(méi)有任何效果,所以我們跳轉(zhuǎn)的界面必須是在StackNavigator中注冊(cè)了的。

官方原話:如果我們this.props.navigation.navigate使用我們尚未定義的路由名稱進(jìn)行呼叫,則不會(huì)StackNavigator發(fā)生任何事情。換句話說(shuō),我們只能導(dǎo)航到已定義的路線StackNavigator- 我們無(wú)法導(dǎo)航到任意組件。
問(wèn)題三:那我們多次跳轉(zhuǎn)同一個(gè)注冊(cè)的界面,又會(huì)出現(xiàn)什么呢?

  • 首先我們將代碼改成
class HomeScreen  extends React.Component {
    render() {
        return (
.
.
.
                    //這里跳轉(zhuǎn)的頁(yè)面是我們已經(jīng)在StackNavigator中注冊(cè)了的,如果是沒(méi)注冊(cè)又會(huì)發(fā)生什么呢
                    onPress={() => this.props.navigation.navigate('Details')}
                    />
.
.
}
class DetailsScreen  extends React.Component {
    render() {
.
.
.
                    //這里跳轉(zhuǎn)的頁(yè)面是我們已經(jīng)在StackNavigator中注冊(cè)了的,如果是沒(méi)注冊(cè)又會(huì)發(fā)生什么呢
                    onPress={() => this.props.navigation.navigate('Details')}
                    />
.
.
}
  • 效果
    多次跳轉(zhuǎn).gif

    總結(jié):多次打開(kāi)DetailsScreen頁(yè)面,會(huì)創(chuàng)建新的DetailsScreen頁(yè)面添加到堆棧
    官方解釋:每次按“轉(zhuǎn)到詳細(xì)信息......再次”按鈕時(shí),它都會(huì)將新的屏幕推到頂部。這是我們?cè)瓉?lái)的比較document.location.href分崩離析的地方,因?yàn)樵诰W(wǎng)絡(luò)瀏覽器中,這些不會(huì)被視為不同的路線,也不會(huì)將新條目添加到瀏覽器歷史記錄中 - navigate因?yàn)镾tackNavigator其行為更像網(wǎng)絡(luò)window.history.pushState:每次調(diào)用時(shí)navigate都會(huì)推送一個(gè)新的路由到導(dǎo)航堆棧。

問(wèn)題四:我們?cè)鯓佑么a控制回到上一個(gè)頁(yè)面呢?其實(shí)這個(gè)就很簡(jiǎn)單了

  • 首先我們?cè)贒etailsScreen中添加代碼
class DetailsScreen  extends React.Component {
    render() {
        return (
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Details Screen</Text>
                <Button
                    title="Go to Details again"
                    //這里跳轉(zhuǎn)的頁(yè)面是我們已經(jīng)在StackNavigator中注冊(cè)了的,如果是沒(méi)注冊(cè)又會(huì)發(fā)生什么呢
                    onPress={() => this.props.navigation.navigate('Details')}
                    />
                <Button
                    title="Go back"
                    onPress={() => this.props.navigation.goBack()}
                    />
            </View>
        );
    }
}

效果就不展示了,和點(diǎn)擊返回按鈕一樣。
經(jīng)過(guò)問(wèn)題三和問(wèn)題四,你肯定會(huì)想到,那如果我們有業(yè)務(wù)的邏輯是常見(jiàn)的要求是能夠返回多個(gè)屏幕 - 例如,如果您在堆棧中有幾個(gè)屏幕深度,并且想要將它們?nèi)砍坊氐降谝粋€(gè)屏幕。官方說(shuō)我們將在“建立一個(gè)簽名流”中討論如何做到這一點(diǎn)
不過(guò)暫時(shí)我還沒(méi)有找到解決辦法,知道請(qǐng)留言

使用路由傳參

跳轉(zhuǎn):
在上面的例子中我們跳轉(zhuǎn)是調(diào)用onPress={() => this.props.navigation.navigate('Details')}
而需要攜帶參數(shù)的跳轉(zhuǎn),其實(shí)也很簡(jiǎn)單,無(wú)非就是跳轉(zhuǎn)多一個(gè)參數(shù),將需要傳遞的參數(shù)以一個(gè)對(duì)象的形式進(jìn)行傳遞
onPress={() => this.props.navigation.navigate('Details',{title:'這是主界面?zhèn)鬟f的title'})}
可以看出這里其實(shí)就是多了{title:'這是主界面?zhèn)鬟f的title'}這個(gè)參數(shù)
使用:
如果你是像我這里一樣傳遞的是title,那么將title設(shè)置給標(biāo)題欄,其實(shí)也很簡(jiǎn)單,在navigationOptions中調(diào)用navigation.state.params.title設(shè)置headerTitle即可

 //設(shè)置頂部導(dǎo)航欄的內(nèi)容
    static navigationOptions = ({navigation, screenProps}) => ({
        //標(biāo)題
        headerTitle: navigation.state.params.title,
        //設(shè)置跳轉(zhuǎn)頁(yè)面左側(cè)返回箭頭后面的文字,默認(rèn)是上一個(gè)頁(yè)面的標(biāo)題
        headerBackTitle: null,
        //頂部標(biāo)題欄的樣式
        headerStyle: styles.headerStyle,
        //頂部標(biāo)題欄文字的樣式
        headerTitleStyle: styles.headerTitleStyle,
    });

這里只是展示了部分navigationOptions 的參數(shù)設(shè)置,詳情見(jiàn)React Navigation或是
react-navigation使用技巧
注意:上面使用我們傳遞的參數(shù)由于navigationOptions已經(jīng)有navigation這個(gè)對(duì)象所以我們使用參數(shù)是調(diào)用navigation.state.params.title,那如果我們要在其他地方使用呢,則調(diào)用this.props.navigation.state.params.title
例如:

 <Text>{this.props.navigation.state.params.title}</Text>

效果圖:

帶參.gif

這里只是部分代碼展示,完整代碼,見(jiàn)頂部項(xiàng)目

StackNavigator和Navigator相比有什么好處呢:
  • 1、新的導(dǎo)航庫(kù)無(wú)論從性能還是易用性上都要大大好于老的Navigator!這是官方原話
  • 2、StackNavigator寫(xiě)起來(lái)更簡(jiǎn)單方便,讀者 可以點(diǎn)擊Navigator自己對(duì)比,尤其這點(diǎn)使用過(guò)Navigator和StackNavigator的人體會(huì)明顯
  • 3、StackNavigator只能跳轉(zhuǎn)已注冊(cè)的界面,類似與安卓只能跳轉(zhuǎn)在清單文件中注冊(cè)的activity一樣,而Navigator沒(méi)有這個(gè)規(guī)則,但是必須將Navigator自身作為一個(gè)屬性相互傳遞,而StackNavigator至少不需要我們手動(dòng)傳遞(作為一個(gè)安卓開(kāi)發(fā)來(lái)說(shuō),我更傾向StackNavigator)

喜歡請(qǐng)點(diǎn)贊,或是關(guān)注,后續(xù)將完善發(fā)布更多的文章,你的鼓勵(lì)就是我的動(dòng)力(程序員最大的動(dòng)力莫過(guò)于同行的鼓勵(lì))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容