React Native NavigationExperimental

前端之家收集整理的这篇文章主要介绍了React Native NavigationExperimental前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Overview

NavigationExperimental是react native的一个新的导航系统,重点是改进<Navigator/>组件.

  • 单向数据流,它使用reducers 来操作最顶层的state 对像,而在<Navigator/>中,当你在子导航页中,不可能操作到app最初打开页面时的state对像,除非,一级级的通过props传递过方法名或函数名,然后在子页面调用这些方法或者函数,来修改某个顶层的数据。
  • 为了允许存在本地和基于 js的导航视图,导航的逻辑和路由,必须从视图逻辑中独立出来。
  • 改进了切换时的场景动画,手势和导航栏

如果你对react native 中的三个导航感到困惑,可以查看导航比较文章

三个导航系统的比较

NavigatorNavigatorIOS 对于新人来说,不知道如何区别它们。一个是基于JS的,而NavigatorIOS则是第三方的开发的只针对ios的本地组件. 而Facebook正在将Navigator 过渡到NavigationExperimental. NavigationExperimental向前兼容navigation库。

NavigationExperimental 通常称为”新的导航”,但其实它是以一种新的方法实现导航逻辑,这样允许作何的视图都可以作为导航的视图 。它包含了一个预编异的组件NavigationAnimatedView来管理场景间的动画。它内部的每一个视图都可以有自己的手势和动画。这些预编译的场景和overlay组件,看起来就会跟平台相一致(ios,android)

Navigator and NavigatorIOS两个都是有状态(即保存各个导航的序顺)的组件,允许你的APP在多个不同的场景(屏幕)之间管理你的导航。这两个导航管理了一个路由栈(route stack),这样就允许我们使用pop(),psh(),and replace()来管理状态。这类似于html5的history API. 这两者的主要区别在于NavigatorIOS是使用了iOS的 UINavigationController类,而Navigator都是基于Javascript。 Navigator适用于两个平台,而NavigatorIOS只能适用于iOS. 如果在一个APP中应用了多个导航组件(Navigator and NavigatorIOS一起使用). 那么在两者之间进行导航过渡,会变得非常困难.

  • NavigationRootContainer允许导航的各个状态(屏幕)保存在app的最顶层.
    • 使用reducer在导航状态中声明设置转换过渡
    • 可以将state永久保存存到硬盘,这样刷新和app更新后,还能获得之前的导航状态
    • 监听打开中的url链接,BackAndroid便于支持返回按纽
  • NavigationReducers 包含了预置的reducers,用来管理导航状态之间的转换过渡。
    • Reducers可以彼此之前进行组合,设置更高级的导航逻辑
  • 导航逻辑可以用于任何的视图
  • NavigationAnimatedView 是一个用来管理不同场景动画的组件,也可以用于Navigator和NavigatorIOS组件
    • 每一个scene可以完全自定义,并且管理它自己的动画和手势
    • 可以有一个Overlay/header,用于跟场景的动画同步
  • NavigationCard 和NavigationHeader可以作为预编译的scenes和overlays. 然后跟NavigationAnimatedView一起使用
  • Facebook会慢慢不支持Navigator,重点会放在NavigationExperimental
  • 它有自己的navigations state和API,这违返了React的单向数据流原则
  • Scene animations and gestures很难自定义
    • 手势可以通过Navigator处理,但是不能基于每一个预编译scene进行自定义
    • Animation 的自定义是模糊的,因为它在Animated库出来之前就有了
  • 可以用于iOS和Android
  • 跟NavigatorIOS一样,只有一个简单的导航条:Navigator.NavigatorBar,和一个breadcrumbs Navigator.BreadcrumbNavigatorBar. 可以看看React Native的官方UIExplorer demo 看看如何使用它们。
    • 动画不如Apple的精致,你可以使用NavigatorIOS.
  • 你可以通过navigationBar属性,提供你自己的navigation bar
  • 包含一 个专有的API,不能很好的兼容其它的app
  • API很小,所以限制了它对Navigator or NavigationStackView的自定义
  • 开发这个组件不是React Native团队,而是属于开源的社区
    • 有很多积压的bug
    • 如果社区将它重构为声明性的(declarative),它将跟NavigationExperimental一起使用的很好
  • 它在iOS UIKit的基础上包装的, 所以它跟其它的本地app是一样的。
  • 支持iOS
  • 包含一个默认的navigation bar. 这个navigation bar不是一个React Native view组件,它的样式只能轻微调整

你整个app的导航状态(state)可以被NavigationStates模式化,一个NavigationState是一个对像。

const myState = {
  key: 'myPage0',myType: 'ExamplePage',myParams: {foo:'bar'},}

一个NavigationParentState 包含一组路由(routes),并且有一个index字段,表示当前的路由

const myState = {
  key: 'myAppTabs',routes: [
    {key: 'home'},{key: 'notifs'},{key: 'settings'},],index: 1,// points to the 'notifs' tab
}

navigation state types在NavigationStateUtils中保存,同时在NavigationStateUtils还有一些函数,通过这些函数可以改变NavigationParentState。

Containers

在NavigationExperimental中提供了一个最顶级的组件,用于维护导航的状态以及处理永久性(将导航保存到硬盘或者从硬盘中读取导航的状态数据)。
如果你使用redux 或者flux,你可以不需要NavigationContainer. 你可以使用现有的stores and providers.

开发者可以为根容器设置一个reducer,reducer会包含整个app的导航逻辑。我们的navigation reducers将会接受最后的导航状态,一个我们需要处理的action. 然后它为我们的app输出一个新的导航装态。为了获得初始化的state,reducers可以在调用时,不需要上一个状态或者action.

<NavigationRootContainer  reducer={MyReducer} renderNavigation={(navigationState, onNavigate) => (
    <Text>Currently at {navigationState.routes[navigationState.index]}</Text>

它也提供了一个针对navigation action的处理器,并且允许reducer被自定义.

在整个应用中,都要传递onNavigate会非常繁锁,因此我们可以提供一个更高阶的”container”组件。

<NavigationRootContainer
  reducer={MyReducer}
  renderNavigation={(navigationState) => <ExampleComponent />}
...

class ExampleComponent {
  render() {
    <Text onPress={() => { this.props.onNavigate(new ExampleAction()) }}>
      This action will work,even though `onNavigate` was not directly passed in
    </Text>
  }
}
ExampleComponent = NavigationContainer.create(ExampleComponent);

如果onNavigation作为一个属性被传递给container,它会覆盖处理程序中包含的组件和所有的子容器.

Reducers

一个导航的reducer是一个action 处理器,它返回当前的navigation state.当调用navigation reducers,你要提供一个可选的prevIoUs state和一个字符串类型的 navigation action.

let state = MyReducer(null,{ type: 'InitialAction' });
//output
> {
    key: 'Root',index: 0,routes: [
      {key: 'Home'},]
  }
state = MyReducer(state,{ type: 'PushPerson',name: 'Christopher' });
//output
> {
    key: 'Root',index: 1,{key: 'Person0',name: 'Christopher'},]
  }

Stack Reducer

常见的导航逻辑是一个’stack’(栈),这可以通过stack reducer来处理

const MyReducer = NavigationStackReducer({
  // First,define the initial parent state that will be used if there was no prevIoUs state.
  initialState: {
    key: 'Root',]
  },getPushedReducerForAction: (action) => {
    if (action.type === 'PushPerson') {
      // We need to push some additional state,that will be defined by this reducer:
      return () => ({
        key: 'Person'+(i++),name: action.name,});
    }
    // In this case we do not need to push,so our reducer for this action is nothing
    return null;
  },});

let state = MyReducer(null,{ type: 'InitAction' });
> {
    key: 'Root',]
  }

state = MyReducer(state,name: 'Christopher' });
> {
    key: 'Root',]
  }

// The back action can be used to pop:
state = MyReducer(state,NavigationRootContainer.getBackAction());
> {
    key: 'Root',]
  }

stack reducer中也可以包含sub-reducers,它需要你实现getReducerForState. 它会为sub-state 返回一个sub-reducer. 当前的sub-state的sub-reducer将会被使用.

Tabs Reducer

Tabs reducer允许你有多个子sub-reducers,但有一个是激活状态。对于每一个action,都会被发送给tabs reducer,它会首先使用active状态的sub-reducer. 如果reducers没有返回一个新的sub-state,则另外的reducers将会获得机会,并进行处理。如果一个不同的tab reducer处理了它,tabs reducer将返回一个新的new sub-state,并且交换active tab.

Find Reducer

Reducers的一个常见模式是组合了多个reducers,当其中一个reducer返回一个新的state时停止。Find Reducer会接受一个reducers数组,然后遍历数据中的每一个元素,直到state改变时,返回这个reducer. 如果这些reducers没有返回一个新的state,find reducer将返回默认的state.

Views

最简单的视图是render当前sub-state的场景(scene). 常用于tabs,因为它不需要转换。

NavigationAnimateView 采用声明API,它使用Animate library向scenes委派动画和手势

NavigationCard和NavigationHeader就是场景和叠加的NavigationAnimateView。这是为了看起来跟iOS或android一样。

<NavigationAnimatedView  navigationState={navigationState} renderScene={(props) => (
    <NavigationCard  key={props.navigationState.key} index={props.index} navigationState={props.navigationParentState} position={props.position} layout={props.layout}>
      <MyInnerView info={props.navigationState} />
    </NavigationCard>
  )}
/>
<NavigationAnimatedView  navigationState={navigationState} renderOverlay={(props) => (
    <NavigationHeader  navigationState={props.navigationParentState} position={props.position} getTitle={state => state.key}
    />
  )}
  renderScene={this._renderScene}
/>

包装了NavigationAnimateView,可以为每一个Scene,render一个NavigationCard. 类似于过时的Navigator. 这是因为它内置了animations和gestures

使用:

render() { return ( <NavigationCardStack  style={styles.main} renderScene={props => <MyPetView  name={props.navigationState.key} species={props.navigationState.species} /> } renderOverlay={props => <NavigationHeader {...props} />} navigationState={{ key: 'MyPetStack',index: 2,routes: [ {key: 'Pluto',species: 'dog'},{key: 'Snoopy',{key: 'Garfield',species: 'cat'},] }} /> ); }

猜你在找的React相关文章