React-Native -- 可继承的Navigator

React-Native中Navigator的继承问题

最近使用React-Native开发程序,在使用Navigator的时候,发现Navigato无法继承。主要原因:Navigator是通过React.CreateClass创建的,与ES6支持的extends并不能很好地兼容,继承的时候不能覆盖相应的方法

使用google在 http://www.jianshu.com/p/08d7d9e34957 中找到了解决方法。大致的思路就是在renderScene中对需要覆盖的方法进行重新的赋值。

不过,这样使用方式不太适合复用。于是重新封装成了一个可继承的Navigator。

备注:React-Native 版本为0.39.2

import React,{Component} from 'react';
import {
    Navigator
} from 'react-native';

export default class CanOverrideNavigator extends React.Component {

    render() {
        return (
            <Navigator
                {...this.props}
                renderScene={(route,navigator) =>this._renderScene(route,navigator)}
            />);
    }


    _renderScene(route,navigator) {
        this.overrideMethodFunc(navigator);
        return this.props.renderScene(route,navigator)
    }

    //设置继承方法
    overrideMethodFunc(navigator) {
        if (this.overrideMethod) {
            return;
        }
        //保存navigator原有的函数
        this._jumpBack = navigator.jumpBack;
        this._jumpForward = navigator.jumpForward;
        this._jumpTo = navigator.jumpTo;
        this._push = navigator.push;
        this._pop = navigator.pop;
        this._replace = navigator.replace;
        this._replaceAtIndex = navigator.replaceAtIndex;
        this._replacePrevIoUs = navigator.replacePrevIoUs;
        this._resetTo = navigator.resetTo;
        this._immediatelyResetRouteStack = navigator.immediatelyResetRouteStack;
        this._popToRoute = navigator.popToRoute;
        this._popToTop = navigator.popToTop;
        this._getCurrentRoutes = navigator.getCurrentRoutes;

        //对navigator的函数进行重新的赋值
        navigator.jumpBack = ()=> {
            this.jumpBack();
        };
        navigator.jumpForward = ()=> {
            this.jumpForward();
        };
        navigator.jumpTo = (route)=> {
            this.jumpTo(route);
        };
        navigator.push = (route)=> {
            this.push(route);
        };
        navigator.pop = ()=> {
            this.pop();
        };
        navigator.replace = (route)=> {
            this.replace(route);
        };
        navigator.replaceAtIndex = (route,index,cb)=> {
            this.replaceAtIndex(route,cb);
        };
        navigator.replacePrevIoUs = (route)=> {
            this.replacePrevIoUs(route);
        };
        navigator.resetTo = (route)=> {
            this.resetTo(route);
        };
        navigator.immediatelyResetRouteStack = (routeStack)=> {
            this.immediatelyResetRouteStack(routeStack);
        };
        navigator.popToRoute = (route)=> {
            this.popToRoute(route);
        };
        navigator.popToTop = ()=> {
            this.popToTop();
        };
        navigator.getCurrentRoutes = ()=> {
            this.getCurrentRoutes();
        };

        this.overrideMethod = true;
    }

    jumpBack() {
        this._jumpBack();
    }

    jumpForward() {
        this._jumpForward();
    }

    jumpTo(route) {
        this._jumpTo(route);
    }

    push(route) {
        this._push(route);
    }

    pop() {
        this._pop();
    }

    replace(route) {
        this._replace(route);
    }

    replaceAtIndex(route,cb) {
        this._replaceAtIndex(route,cb);
    }

    replacePrevIoUs(route) {
        this._replacePrevIoUs(route);
    }

    resetTo(route) {
        this._resetTo(route);
    }

    immediatelyResetRouteStack(routeStack) {
        this._immediatelyResetRouteStack(routeStack);
    }

    popToRoute(route) {
        this._popToRoute(route);
    }

    popToTop() {
        this._popToTop();
    }

    getCurrentRoutes() {
        return this._getCurrentRoutes();
    }
}

使用方式

import React,{Component} from 'react';
import CanOverrideNavigator from './CanOverrideNavigator';
import {
    View,Text,TouchableHighlight,Navigator
} from 'react-native';


export default class TestNavigator extends React.Component {
    render() {
        return (
            <MyNavigator
                ref="navigator"
                initialRoute={{component: OneContainer}}
                configureScene={()=> {
                    return Navigator.SceneConfigs.PushFromright;
                }}
                renderScene={this._renderScene.bind(this)}
            />
        );
    }

    _renderScene(route,navigator) {
        let Component = route.component;
        return (
            <Component
                navigator={navigator}
                route={route}
            />
        )
    }
}

class MyNavigator extends CanOverrideNavigator {
    push(rotue) {
        console.log('before push');
        super.push(rotue);
        console.log("after push");
    }

    pop() {
        console.log('before pop');
        super.pop();
        console.log("after pop");
    }
}

class OneContainer extends React.Component {
    render() {
        return (<TouchableHighlight
            style={{padding:20}}
            onPress={()=> {
                this.props.navigator.push({component: TwoContainer})
            }}
        >
            <Text>OneContainer</Text>
        </TouchableHighlight>);
    }
}

class TwoContainer extends React.Component {
    render() {
        return (<TouchableHighlight
            style={{padding:20}}
            onPress={()=> {
                this.props.navigator.pop()
            }}
        >
            <Text>TwoContainer</Text>
        </TouchableHighlight>);
    }
}

相关文章

react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接...
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc ...