新手理解Navigator的教程

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的用法:

相關文章
相關標籤/搜索