React-Native -- 可继承的Navigator

时间:2021-05-30 18:59:56

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, index, 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, index, cb) {
this._replaceAtIndex(route, index, 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>);
}
}