react-native-navigation-helper

0.0.10 • Public • Published

react-native-navigation-helper

这个包是对 react-native-navigation 的扩展,它能让你更轻松地在项目中使用 react-native-navigation 。

遇到问题?请反馈到这里


Usage

  1. 首先需安装 react-native-navigation ,可参考这个网址进行安装:

    https://wix.github.io/react-native-navigation/#/docs/Installing

    版本要求 >= 3.2.0,更低版本的没测试过,不确定是否兼容。

  2. 使用 npm 安装 react-native-navigation-helper :

    npm install react-native-navigation-helper --save
    
  3. 修改项目的启动文件(默认为根目录下的 ./index.js):

    import $Nav from 'react-native-navigation-helper';
    import App from './App';
     
    $Nav.init({
        pages: {
            'app': App
        },
        layout: {
            root: {
                component: {
                    name: 'app'
                }
            }
        }
    });


$Nav.init(options)

options.defaultOptions:设置默认选项

$Nav.init({
    // .......
    defaultOptions: {
        layout: {
            backgroundColor: 'yellow'
        }
    }
    // ......
});

更多可配置参数请参考这里:

https://wix.github.io/react-native-navigation/#/docs/styling?id=options-object-format

options.pages:key-value,项目中的所有页面(Screen)

建议将所有页面文件放在同一个文件夹下,例如 ./pages/

|--node_modules
|--pages
|    |--index.js
|    |--news.js
|    |--detail.js
|--package.json

所有页面类都应从 $Nav.Page 继承,否则可能无法使用某些功能:

// import React 是必须的
import React from 'react';
import {View, Text} from 'react-native';
 
// $Nav 是全局变量,在此文件中不用 import
class News extends $Nav.Page {
    constructor(props){
        super(props);
    }
    
    render() {
        return (
            <View>
                <Text>This is News</Text>
            </View>
        );
    }
}
 
export default News;

$Nav 是全局变量,除了在 ./index.js ,在其它文件中不用 import 它。

可单独用一个文件来管理所有的页面,例如可以是 ./pages/_.js

export default {
    // 这里的 key 是你对每个页面的命名
    index: require('./index').default,
    news: require('./news').default,
    detail: require('./detail').default,
    // ......
};

则在 ./index.js 中可这样使用:

// ......
import pages from './pages/_';
 
$Nav.init({
    // ......
    pages: pages,
    // ......
});

options.layout:object or function,基本布局

可以是 object,也可以是返回 object 的 function。

$Nav.init({
    // ......
    layout: {
        root: {
            stack: {
                children: [{
                    component: {
                        name: 'index' // 这里的值是 options.pages 中某个页面对应的 key
                    }
                }]
            }
        }
    }
    // ......
});

更多配置可参考这里:

https://wix.github.io/react-native-navigation/#/docs/layout-types

options.promises:array,一组 Promise,一般用来预加载资源

例如,如果要用到 react-native-vector-icons,可在 options.promises 中预加载要用到的图标:

// ......
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
 
$Nav.init({
    // ......
    promises: [
        MaterialIcons.getImageSource('home', 25),
        MaterialIcons.getImageSource('menu', 25)
    ],
    // promises 中每一个 Promise 获取到的数据将依次传入这个 function 中
    layout: function(iconHome, iconMenu){
        return {
            root: {
                stack: {
                    children: [{
                        component: {
                            name: 'index'
                        }
                    }],
                    options: {
                        topBar: {
                            leftButtons: [{
                                id: 'btnLeft',
                                icon: iconMenu
                            }]
                        }
                    }
                }
            }
        };
    }
    // ......
});


导航

为可点击的元素添加 $href 属性,能轻松实现在页面间的导航:

<View>
    <Button title="Click Me" $href="detail"/>
</View>

$href 属性的值可以是 string ,也可以是 object

$href 属性的值是 string 时,它指的是一个页面的名字(在 options.pages 中设置的)。当用户点击该元素后,将打开这个页面。

react-native-navigation-helper 会根据当前的环境智能地判断是应该使用 push 打开,还是使用 modaloverlay 打开。

但开发者的需求是有可能非常态的,如果默认的打开方式不适合你的需求,你可以明确地指定打开方式:

<View>
    <Button
        title="Click Me"
        $href={{
            url: 'detail',
            type: 'modal'
        }}/>
</View>

上面的示例明确地要求以 modal 方式打开 detail 页面。

type 的值可以是 pushmodaloverlay

如果需要传递参数给打开的页面,则使用 data 传递:

<View>
    <Button
        title="Click Me"
        $href={{
            url: 'detail',
            type: 'modal',
            data: {id: 100}
        }}/>
</View>

还可以设置在导航后执行的 function:

<View>
    <Button
        title="Click Me"
        $href={{
            url: 'detail',
            type: 'modal',
            data: {id: 100},
            afterNav: this.$close
        }}/>
</View>

上面的示例在导航后执行 this.$close() 关闭当前面。

如果希望在 js 代码中进行导航,则可用 this.$go(cmd)

class Index extends $Nav.Page {
    constructor(props) {
        super(props);
    }
    
    goDetail = () => {
        this.$go('detail');
    }
    
    render() {
        return (
            <View>
                <Button title="Navigation to Detail" onPress={this.goDetail}/>
            </View>
        );
    }
}

this.$go(cmd) 的参数与 $href 属性的值一样,也可以是 object

this.$go({
    url: 'detail',
    type: 'modal',
    data: {id: 100}
});


$Nav.Page

所有的页面都应从 $Nav.Page 继承。

$Nav.Page 继承的页面有以下属性、方法:

import React from 'react';
import {View, Text, Button} from 'react-native';
 
class News extends $Nav.Page {
    constructor(props){
        super(props);
        
        // 当前页面的 opener 传递过来的参数
        console.log(props.$data);
    }
    
    render() {
        return (
            <View>
                <Text>This is News</Text>
                <View>
                    <Button title="Close" onPress={this.$close}/>
                </View>
            </View>
        );
    }
}
 
export default News;


路由拦截

通过路由拦截,可阻止页面导航或改变导航页面。

$Nav.init(options) 参数中配置 beforeNav,它是一个 function,在页面导航之前执行,它需返回 Promise

$Nav.init({
    // ......
    beforeNav: function(fromPage, to, toObj){
        if(to == 'profile' && !isAuthorized()){
            fromPage.$go({
                url: 'login',
                type: 'modal'
            });
            return false;
        }
        return true;
    },
    // ......
});

beforeNav 会被传入三个参数,第一个参数 fromPage 是当前页面对象,第二个参数 to 是即将导航到的页面的名字,第三个参数是即将导航到的页面的定义,它是 $Nav.Page classoptions.layout 中定义的有基本布局的页面(参考后面的文档)。

如果返回的不是 Promise,返回 则阻止导航。

如果返回 Promise,则 resolve 将阻止导航。



sideMenu

sideMenu 有左边栏、右边栏、中间主体部分。其中左边栏和右边栏是可选的。

参考:https://wix.github.io/react-native-navigation/#/docs/layout-types?id=sidemenu

$Nav.init({
    // ......
    promises: [
        MaterialIcons.getImageSource('menu', 25)
    ],
    layout: function(iconMenu){
        return {
            root: {
                sideMenu: {
                    left: {
                        component: {
                            name: 'sidemenuleft'
                        }
                    },
                    center: {
                        stack: {
                            children: [{
                                component: {
                                    name: 'index',
                                    options: {
                                        topBar: {
                                            leftButtons: [{
                                                id: 'btnToggleLeft',
                                                icon: iconMenu
                                            }]
                                        }
                                    }
                                }
                            }]
                        }
                    }
                }
            }
        };
    }
    // ......
});

sideMenu 由三个页面组成。在中间主体部分的页面中,可用 this.$toggleLeft() 切换左边栏的显示状态:

class Index extends $Nav.Page {
    constructor(props) {
        super(props);
    }
    
    navigationButtonPressed = ({buttonId}) => {
        if (buttonId === 'btnToggleLeft') {
            this.$toggleLeft();
        }
    }
    
    render() {
        // ......
    }
}

也可用 this.$openLeft()this.$closeLeft() 打开、关闭左边栏。

可用 this.$left 访问左边栏页面对象。

同理,可用 this.$toggleRight()this.$openRight()this.$closeRight() 切换右边栏显示状态、打开右边栏、关闭右边栏,用 this.$right 访问右边栏页面对象。

在左边栏或右边栏页面中,可用 this.$open()this.$close() 打开、关闭自己:

class SideMenuLeft extends $Nav.Page {
    render() {
        return (
            <View>
                <Button title="Close" onPress={this.$close}/>
            </View>
        );
    }
}

也可用 this.$center 访问中间主体页面对象。



bottomTabs

bottomTabs 的每个选项卡页面中,可用 this.$tab(tabIndex) 切换到指定的选项卡:

<Button title="tab1" onPress={()=>this.$tab(1)}/>

可用 this.$tabsHide()this.$tabsShow() 显示、隐藏底部的选项卡栏:

<Button title="hide tabs" onPress={()=>this.$tabsHide()}/>


导航到有基本布局的页面

如果导航的目标页不是简单的 $Nav.Page,而是由多个 $Nav.Page 组合而成的有基本布局的页面(例如 sideMenubottomTabs),则需在 $Nav.init(options)layout 中进行配置:

$Nav.init({
    // ......
    layout: {
        root: {
            // ......
        },
        shop: {
            bottomTabs: {
                children: [{
                    stack: {
                        children: [{
                            component: {
                                name: 'shopindex'
                            }
                        }],
                        options: {
                            bottomTab: {
                                text: 'Shop',
                                icon: require('./imgs/tab0.png')
                            }
                        }
                    }
                }, {
                    component: {
                        name: 'orders',
                        options: {
                            bottomTab: {
                                text: 'Orders',
                                icon: require('./imgs/tab1.png')
                            }
                        }
                    }
                }]
            }
        }
    },
    // ......
});

之后就可像下面这样导航到上面配置的 shop 页了:

<Button title="Shop" $href="shop"/>

或者:

this.$go({
    url: 'shop',
    type: 'modal'
});

layout 根节点 key 会被当作页面的名字,因此不能与其它页面的名字重复。

对于打开的由多个页面组成的有基本布局的页面,无法用 this.$close() 关闭它,而应该用 this.$closeWin()



$Nav.setOptions(componentId, options)

react-native-navigation 中的 Navigation.mergeOptions(componentId, options) 等效。

参考:https://wix.github.io/react-native-navigation/#/docs/styling?id=setting-styles-dynamically

在一个页面中,

this.$setOptions({
    topBar: {
        title: {
            text: 'Hello CYF'
        }
    }
});

$Nav.setOptions(this.props.componentId, {
    topBar: {
        title: {
            text: 'Hello CYF'
        }
    }
});

是等效的。



更多....

react-native-navigation-helper 提供的功能是有限的,可能并不能完全满足你的需求。你可以用 $Nav.nav 直接使用 react-native-navigation 中的 Navigation 对象。当然,你也可以直接在项目中 import react-native-navigation。

Package Sidebar

Install

npm i react-native-navigation-helper

Weekly Downloads

0

Version

0.0.10

License

ISC

Unpacked Size

48.6 kB

Total Files

7

Last publish

Collaborators

  • caoyongfeng