Navigator是RN提供的一個路由工具,不過缺陷是沒有預設一個路由配置文件,因此致使整個結構相似goto語法的,你能夠跳轉到任意的頁面。先來一個最簡單的Navigator:node
var { View, Navigator } = React;var FirstPageComponent = require('./FirstPageComponent');var SampleComponent = React.createClass({ render: function() { var defaultName = 'FirstPageComponent'; var defaultComponent = FirstPageComponent; return ( <Navigator initialRoute={{ name: defaultName, component: defaultComponent }} configureScene={() => { return Navigator.SceneConfigs.VerticalDownSwipeJump; }} renderScene={(route, navigator) => { let Component = route.component; if(route.component) { return <Component {...route.params} navigator={navigator} /> } }} /> ); } });
這裏來逐行解釋代碼的功效:react
第三行: 一個初始首頁的component名字,好比我寫了一個component叫HomeComponent,那麼這個name就是這個組件的名字【HomeComponent】了。ios
第四行: 這個組件的Class,用來一下子實例化成 <Component />標籤react-native
第七行: initialRoute={{ name: defaultName, component: defaultComponent }} 這個指定了默認的頁面,也就是啓動app以後會看到界面的第一屏。 須要填寫兩個參數: name 跟 component。app
第八,九,十行: configureScene={() => { return Navigator.SceneConfigs.VerticalDownSwipeJump; }} 這個是頁面之間跳轉時候的動畫,具體有哪些?能夠看這個目錄下,有源代碼的: node_modules/react-native/Libraries/CustomComponents/Navigator/NavigatorSceneConfigs.js工具
最後的幾行: renderScene={(route, navigator) => { let Component = route.component; if(route.component) { return <Component {...route.params} navigator={navigator} /> } }} /> );動畫
這裏是每一個人最疑惑的,咱們先看到回調裏的兩個參數:route, navigator。經過打印咱們發現route裏其實就是咱們傳遞的name,component這兩個貨,navigator是一個 Navigator的對象,爲何呢,由於它有push pop jump...等方法,這是咱們等下用來跳轉頁面用的那個navigator對象。ui
if(route.component) { return <Component {...route.params} navigator={navigator} /> }
這裏有一個判斷,也就是若是傳遞進來的component存在,那咱們就是返回一個這個component,結合前面 initialRoute 的參數,咱們就是知道,這是一個會被render出來給用戶看到的component,而後navigator做爲props傳遞給了這個 component。this
因此下一步,在這個FirstPageComponent裏面,咱們能夠直接拿到這個 props.navigator:code
var { View, Text, TouchableOpacity } = React;var SecondPageComponent = require('./SecondPageComponent');var FirstPageComponent = React.create({ getInitialState: function() { return {}; }, componentDidMount: function() { }, _pressButton: function() { const { navigator } = this.props; //或者寫成 const navigator = this.props.navigator; //爲何這裏能夠取得 props.navigator?請看上文: //<Component {...route.params} navigator={navigator} /> //這裏傳遞了navigator做爲props if(navigator) { navigator.push({ name: 'SecondPageComponent', component: SecondPageComponent, }) } }, render: function() { return ( <View> <TouchableOpacity onPress={this._pressButton}> <Text>點我跳轉</Text> </TouchableOpacity> </View> ); } });
這個裏面建立了一個能夠點擊的區域,讓咱們點擊能夠跳到SecondPageComponent這個頁面,實現頁面的跳轉。 如今來建立SecondPageComponent,而且讓它能夠再跳回FirstPageComponent:
var { View, Text, TouchableOpacity, } = React;var FirstPageComponent = require('./FirstPageComponent');var SecondPageComponent = React.create({ getInitialState: function() { return {}; }, componentDidMount: function() { }, _pressButton: function() { const { navigator } = this.props; if(navigator) { //很熟悉吧,入棧出棧~ 把當前的頁面pop掉,這裏就返回到了上一個頁面:irstPageComponent了 navigator.pop(); } } render: function() { <View> <TouchableOpacity onPress={this._pressButton}> <Text>點我跳回去</Text> </TouchableOpacity> </View> } });
大功告成,能進能出了。
關於官方文檔裏有個東西,這裏說一下:
getCurrentRoutes() - 獲取當前棧裏的路由,也就是push進來,沒有pop掉的那些jumpBack() - 跳回以前的路由,固然前提是保留如今的,還能夠再跳回來,會給你保留原樣。jumpForward() - 上一個方法不是調到以前的路由了麼,用這個跳回來就行了jumpTo(route) - Transition to an existing scene without unmountingpush(route) - Navigate forward to a new scene, squashing any scenes that you could jumpForward topop() - Transition back and unmount the current scenereplace(route) - Replace the current scene with a new routereplaceAtIndex(route, index) - Replace a scene as specified by an indexreplacePrevious(route) - Replace the previous sceneimmediatelyResetRouteStack(routeStack) - Reset every scene with an array of routespopToRoute(route) - Pop to a particular scene, as specified by its route. All scenes after it will be unmountedpopToTop() - Pop to the first scene in the stack, unmounting every other scene
這些都是navigator能夠用的public method,就是跳轉用的,裏面有些帶參數的XXX(route),新手第一次看這個文檔會疑惑,這個route參數是啥呢,這個route就是:
renderScene={(route, navigator) =>
這裏的route,最基本的route就是:
var route = { name: 'LoginComponent', component: LoginComponent, }
這種格式。這個地方有點模糊的,在這裏先說清楚了。
而後下面要討論,怎麼傳遞參數過去,或者從對方獲取參數。 傳遞參數,經過push就能夠了。 好比在一個 press的事件裏:
//FirstPageComponent.jsvar { View, Text, TouchableOpacity } = React;var SecondPageComponent = require('./SecondPageComponent');var FirstPageComponent = React.create({ getInitialState: function() { return { id: 2, }; }, componentDidMount: function() { }, _pressButton: function() { const { navigator } = this.props; if(navigator) { navigator.push({ name: 'SecondPageComponent', component: SecondPageComponent, //這裏多出了一個 params 其實來自於<Navigator 裏的一個方法的參數... params: { id: this.state.id } }); } } render: function() { return ( <View> <TouchableOpacity onPress={this._pressButton}> <Text>點我跳轉並傳遞id</Text> </TouchableOpacity> </View> ); } });
params的來歷:
// index.ios.js <Navigator initialRoute={{ name: defaultName, component: defaultComponent }} configureScene={() => { return Navigator.SceneConfigs.VerticalDownSwipeJump; }} renderScene={(route, navigator) => { let Component = route.component; if(route.component) { //這裏有個 { ...route.params } return <Component {...route.params} navigator={navigator} /> } }} />
這個語法是把 routes.params 裏的每一個key 做爲props的一個屬性:
navigator.push({ name: 'SecondPageComponent', component: SecondPageComponent, params: { id: this.state.id } });
這裏的 params.id 就變成了 <Navigator id={} 傳遞給了下一個頁面。 因此 SecondPageComponent就應該這樣取得 id:
//SecondPageComponent.jsvar { View, Text, TouchableOpacity, } = React;var FirstPageComponent = require('./FirstPageComponent');var SecondPageComponent = React.create({ getInitialState: function() { return { id: null }; }, componentDidMount: function() { //這裏獲取從FirstPageComponent傳遞過來的參數: id this.setState({ id: this.props.id }); }, _pressButton: function() { const { navigator } = this.props; if(navigator) { navigator.pop(); } } render: function() { return ( <View> <Text>得到的參數: id={ this.state.id }</Text> <TouchableOpacity onPress={this._pressButton}> <Text>點我跳回去</Text> </TouchableOpacity> </View> ); } });
這樣在頁面間傳遞的參數,就能夠獲取了。
而後就是返回的時候,也須要傳遞參數回上一個頁面: 可是navigator.pop()並無提供參數,由於pop()只是從 [路由1,路由2,路由3。。。]裏把最後一個路由踢出去的操做,並不支持傳遞參數給倒數第二個路由,這裏要用到一個概念,把上一個頁面的實例或者回調方 法,做爲參數傳遞到當前頁面來,在當前頁面操做上一個頁面的state:
這是一個查詢用戶信息的例子,FirstPageComponent傳遞id到SecondPageComponent,而後SecondPageComponent返回user信息給FirstPageComponent
//FirstPageComponent.jsvar { View, Text, TouchableOpacity } = React;var SecondPageComponent = require('./SecondPageComponent');var FirstPageComponent = React.create({ getInitialState: function() { return { id: 2, user: null, }; }, componentDidMount: function() { }, _pressButton: function() { var _this = this; const { navigator } = this.props; if(navigator) { navigator.push({ name: 'SecondPageComponent', component: SecondPageComponent, params: { id: this.state.id //從SecondPageComponent獲取user getUser: function(user) { _this.setState({ user: user }) } } }); } } render: function() { if( this.state.user ) { return( <View> <Text>用戶信息: { JSON.stringify(this.state.user) }</Text> </View> ); }else { return( <View> <TouchableOpacity onPress={this._pressButton}> <Text>查詢ID爲{ this.state.id }的用戶信息</Text> </TouchableOpacity> </View> ); } } });
而後再操做SecondPageComponent:
//SecondPageComponent.jsUSER_MODELS = { 1: { name: 'mot', age: 23 }, 2: { name: '晴明大大', age: 25 } };var { View, Text, TouchableOpacity, } = React;var FirstPageComponent = require('./FirstPageComponent');var SecondPageComponent = React.create({ getInitialState: function() { return { id: null }; }, componentDidMount: function() { //這裏獲取從FirstPageComponent傳遞過來的參數: id this.setState({ id: this.props.id }); }, _pressButton: function() { const { navigator } = this.props; if(this.props.getUser) { var user = USER_MODELS[this.props.id]; this.props.getUser(user); } if(navigator) { navigator.pop(); } } render: function() { return( <View> <Text>得到的參數: id={ this.state.id }</Text> <TouchableOpacity onPress={this._pressButton}> <Text>點我跳回去</Text> </TouchableOpacity> </View> ); } });
看下效果如何吧。
下面還有Navigator配合TabBarIOS的用法: