54

RN实践之科学使用StackNavigator

 6 years ago
source link: https://mp.weixin.qq.com/s/gY_Jpr-Z8o8eVaiUjWJfOQ
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

开发过iOS的同学应该都知道UINavigationController这个类,它是大多数App管理页面的导航控制器,在多个页面的App中可以方便地进行页面的导航和定位。RN里也存在一个类似的组件叫做StackNavigator

StackNavigator是ReactNavigation中的一个以栈结构管理页面的导航组件。 

ReactNavigation是RN官方在0.44版本后推出的一个专门用来管理页面的导航器组件库,取代了之前的Navigator。

先看看如何初始化这个组件

官方的示例大概是这样的:

const Root = StackNavigator(
  {
    Page1: {
      screen: Page1Screen,
    },
    Page2: {
      screen: Page2Screen,
    },
  },
  {
    ...导航配置参数
  }
);

AppRegistry.registerComponent('Root', () => Root);

根据这个示例我创建出了导航组件并将所有页面注册到了导航中。

思考:如何控制初始化参数?

在实际开发中,常常会遇到需要从Native端获取一些初始化参数去初始化StackNavigator的情况,所以我改变了一下初始化的方法。大概是这样的:

function obtainRootNavigator(root) {
  const RootNavigator = StackNavigator(
    {
      Page1: {
        screen: Page1Screen,
      },
      Page2: {
        screen: Page2Screen,
      },
    },
    {
      initialRouteName:root,
    },
  );
  return RootNavigator;
}

class Root extends Component {
  
  constructor(props) {
    super(props);
    this.state = {
      root: 'page1',
    };
  }
  
  componentDidMount() {
    NativeModules.myNativeData.read('',(result)=>{
        this.setState({root:result.root});
    });
  }

  render() {
    const RootNavigator = obtainRootNavigator(this.state.root);
    if (RootNavigator) {
      return (<RootNavigator/>);
    }
    return (<LoadingComponent/>);
  }
}

AppRegistry.registerComponent('Root', () => Root);

上面的示例里,我创建了一个Root的组件,它的作用是在组件加载完成后去获取Native端的数据,根据Native端的数据决定导航控制器的根视图。通过这个Root组件,我就可以灵活地控制RootNavigator的初始化参数了。

再看看怎么进行页面的导航

先来看看官方是怎么示例的:

class Page1Screen extends Component {
  render() {
    return (
      <Button
        onPress={() => this.props.navigation.navigate('Page2', {title: 'Page2'})}
        title="Go to Page2"
      />
    );
  }
}

class Page2Screen extends Component {
  render() {
    return (
      <Button
        onPress={() => this.props.navigation.goBack()}
        title="Back to Page1"
      />
    );
  }
}

在还不知道如何使用dispatch函数的时候navigategoBack函数已经足够使用了,如果对dispatch函数有兴趣的话可以看下dispatch相关的介绍

从示例里可以看到每个被注册到StackNavigator中的页面组件都有一个navigation属性,通过其携带的导航函数可以方便地进行页面导航操作。

这个navigation属性类似于iOS导航控制器里的self.navigationController。

但是又有不一样的地方:每个页面的navigation属性只能在它所属页面处于栈顶时进行导航操作。

思考:如何定义全局可用的导航方法?

在实际开发过程中,我们还想要更加方便地调取导航方法,所以我们希望定义一个全局可用的导航方法。

由于每个页面的navigation都不一样,而且只能栈顶的navigation可以执行跳转,想要定义一个全局可用的导航方法,就必须一直更新navigation属性,这也太麻烦了。

有没有别的方法?

于是我去翻ReactNavigation的官方文档,也没有找到相关的介绍,难道只能不停更新navigation么,强迫症患者表示不能忍。最终,在利用组件的ref属性查看StackNavigator属性时找到了答案:

  • 先用一个全局示例引用当前的navigator对象

...
render() {
  return (
  <MyNavigator 
    ref={(navigator) => {CustomStore.navigator = navigator;}}
  />);
}
...
  • 再定义一个自己的导航方法,这里以navigate为例

export default new class CustomStore {
  ...
  navigate = (pageName, params) => {
    const navigation = this.navigator._navigation;
    const { navigate } = navigation;
    navigate && navigate(pageName, params);
  };
  ...
}();

答案就是当我们通过ref引用了StackNavigator组件后,可以获取到一个_navigation属性,这个属性是可以进行全局导航的!利用这个属性,就可以实现全局可用的导航方法了。

思考:如何获取到栈的信息?

当我们有了全局可以调用的导航方法后,我们就需要根据栈的信息进行管理,例如:我们定义一个全局可用的goBack函数,当栈退回到根页面时,退出当前RNApp。 其实这个答案,与上一个问题的答案相同:

export default new class CustomStore {
  ...
  goBack = () => {
    const navigation = this.navigator._navigation;
    const { index } = this.navigator.state.nav;
    if (index === 0) {
      //关闭当前RNApp
      retrun;
    }
    navigation.goBack();
  };
  ...
}();

我们通过引用到的StackNavigator,获取到它的state,StackNavigator所包含的栈信息都就在这个state中了。

以上都是在平时开发过程中总结出来的一些比较基础的StackNavigator的一些使用技巧,拿出来分享一下,同大家一起学习进步。

Image

部门招聘

高级Java开发工程师

工作职责:

1、负责58同城APP,58同镇等相关后端研发工作;

2、负责基础平台的架构设计,核心代码开发;

3、调研并掌握业内通用技术方案,引入项目迭代,提升研发效率;

职位要求:

1、3年以上Java互联网项目开发经验;

2、Java基础扎实,编码规范,程序具备较高的健壮性,熟悉常用设计模式;

3、对MVC框架、RPC框架、基础服务组件等有深入的研究;

4、掌握Linux环境下的网络编程、多线程编程,数据结构和算法能力良好;

5、对高并发高可用系统设计有深入的实践经验;

6、具有高度的责任心、勇于承担责任,能承受较强的工作压力;

7、积极主动,敢于接受挑战,有较强的团队合作精神;

高级前端研发工程师

工作职责:

1、负责58同城App前端产品研发;

2、负责58同城前端无线产品某一技术方向,人才培养;

3、前端研发所需类库、框架、脚手架搭建;

4、交互模式调研及创新(React,ReactNative);

职位要求:

1、计算机及相关专业本科以上学历;

2、3年以上前端开发经验,负责过复杂应用的前端设计和开发 ;

3、精通web前端技术(js/css/html),熟悉主流框架类库的设计实现、w3c标准,熟悉ES6/7优先;

4、熟悉前端模块化开发方式(commonjs/webpack …);

5、熟悉移动端开发、自适应布局和开发调试工具,熟悉hybrid app开发;

6、掌握一门后端语言(node/java/php...),对前后端合作模式有深入理解;

7、有良好的产品意识和团队合作意识,能够和产品、UI交互部门协作完成产品面向用户端的呈现;

8、有技术理想,致力于用技术去推动和改变前端研发;

9、熟悉Vue/React/ReactNative优先,有BAT等公司经验优先;

高级Android开发工程师

岗位描述:

1、负责58同城App的研发工作;

2、肩负平台化任务(插件框架,Walle,Hybrid,WubaRN) ;

3、维护和开发服务库,公共库的工作;

4、调研Android前端技术;

5、提升开发效率和应用性能;

职位要求:

1、2年以上的Android开发工作经验;

2、精通Java语言,精通Android Studio开发,了解Gradle编译;

3、精通常用算法、数据结构和架构设计;

4、了解Android性能限制及优化方案;

5、了解常用的开源工具:Volley,RxJava,Fresco等等;

6、了解git, maven等等工具;

7、有插件开发经验,Hybrid开发经验,ReactNative开发经验优先;

8、积极主动、喜欢挑战,有强烈的创业精神,能承受高强度的工作压力;

以上如有小伙伴感兴趣,请发送简历到:

[email protected]


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK