翻譯|React-navigation導(dǎo)航系統(tǒng)(3)-高級指南


title: 翻譯|React-navigation導(dǎo)航系統(tǒng)(3)-高級指南
date: 2017-03-29 16:41:19
categories: 翻譯
tags: React-Native


Redux Intergration

為了在redux中處理app的navigation state,你可以傳遞你自己的navigation prop到一個navigator.你的navigation prop必須提供當(dāng)前的state,還有就是處理navigation配置項的dispatcher.

使用redux,你的app state由reducer來定義.每一個navigation router都有一個reducer,叫做getStateForAction.下面是一在redux應(yīng)用中使用navigators的簡單實例:

import { addNavigationHelpers } from 'react-navigation';

const AppNavigator = StackNavigator(AppRouteConfigs);

const navReducer = (state, action) => {
  const newState = AppNavigator.router.getStateForAction(action, state);
  return newState || state;
};

const appReducer = combineReducers({
  nav: navReducer,
  ...
});

@connect(state => ({
  nav: state.nav,
}))
class AppWithNavigationState extends React.Component {
  render() {
    return (
      <AppNavigator navigation={addNavigationHelpers({
        dispatch: this.props.dispatch,
        state: this.props.nav,
      })} />
    );
  }
}

const store = createStore(appReducer);

class App extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <AppWithNavigationState />
      </Provider>
    );
  }
}

一旦按照實例操作,navigation state就存儲在redux的store中,這樣就可以使用redux的dispatch函數(shù)來發(fā)起navigation的actions.

牢記在心,當(dāng)一個navigator給定一個navigationprop,他將失去內(nèi)部state的控制權(quán).這意味著現(xiàn)在你來負(fù)責(zé)state的持久化,處理任何的深度鏈接,整合Back按鈕等操作.

當(dāng)你的navigator是巢式的時候,Navigation state自動從一個navigator傳遞到另一個navigator.注意,為了讓子代navigator可以從父代navigator接收state,它應(yīng)該定義為一個screen.

對應(yīng)上面的實例,你可以定義AppNavigator包含一個巢式的TabNavigator:

 const AppNavigator = StackNavigator({
  Home: { screen: MyTabNavigator },
});

在這個實例中,一旦你在AppWithNavigationStateconnect AppNavigator到Redux,MyTabNavigation將會自動接入到navigation state 作為navigtion的prop.

Web Integration

React Navigation routers工作在web環(huán)境下允許你和原生app共享導(dǎo)航的邏輯.綁定在react-navigation的視圖目前只能工作在React Native下,但是在react-primitives項目中可能會有所改變.

示例程序

這個網(wǎng)站由React Navigation構(gòu)建,使用了createNavigationTabRouter.
看看網(wǎng)站的源代碼app.js

app如何獲得渲染參看server.js.在瀏覽器中,使用[BrowserAppContainer.js]來喚醒和獲得渲染.

更多內(nèi)容,很快呈現(xiàn)

不久會有詳細(xì)的教程.

Deep Linking

這一部分指南中,我們將設(shè)置app來處理外部URIs.讓我們從SimpleApp開始
getting start的指南

在這個示例中,我們想使用類似mychat://chat/Taylor的URI來打開我們的app,直接連接到Taylor的chat page.

Configuration

在前面我們定義了navigator想下面這樣:

 const SimpleApp = StackNavigator({
  Home: { screen: HomeScreen },
  Chat: { screen: ChatScreen },
});

我們想讓path類似chat/Taylor鏈接到“Chat”screen,傳遞user作為參數(shù).我們重新定義我們的chat screen使用一個path來告訴router需要匹配的path和需要提取的參數(shù).這個路徑配置為chat/:user.

 const SimpleApp = StackNavigator({
  Home: { screen: HomeScreen },
  Chat: {
    screen: ChatScreen,
    path: 'chat/:user',
  },
});

URI的前綴

下面配置navigation container來提取app的path.當(dāng)配置在頂層navigator上的時候,我們提供containerOperations,

 const SimpleApp = StackNavigator({
  ...
}, {
  containerOptions: {
    // on Android, the URI prefix typically contains a host in addition to scheme
    URIPrefix: Platform.OS == 'android' ? 'mychat://mychat/' : 'mychat://',
  },
});

iOS

基于mychat://URI圖式配置原生的iOS app.
SimpleApp/ios/SimpleApp/AppleDelegate.m

 // Add the header at the top of the file:
#import <React/RCTLinkingManager.h>

// Add this above the `@end`:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
  return [RCTLinkingManager application:application openURL:url
                      sourceApplication:sourceApplication annotation:annotation];
}

在Xcode里,打開項目的simpleApp/ios/SimpleApp.xcodeproj.在邊欄中選擇項目導(dǎo)航到info tab.向下滑動到“URL Types”并且添加一個.在新的URL type,設(shè)定名稱和url圖式對應(yīng)想導(dǎo)航到的url圖式.

現(xiàn)在可以在Xcode中點擊play,或者在命令行運(yùn)行

react-native run-ios

為了在iOS中測試URI,在safari中打開mychat://chat/Taylor

Android

為了在Andorid中鏈接外鏈,可以在manifest中創(chuàng)建一個新的intent.
SimpleApp/android/app/src/main/AndroidManifest.xmlMainActivity內(nèi)添加新的VIEWtypeintent-filter.

 <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="mychat"
          android:host="mychat" />
</intent-filter>

現(xiàn)在,重新運(yùn)行:

 react-native run-android

在Android中測試intent操作,運(yùn)行

 adb shell am start -W -a android.intent.action.VIEW -d "mychat://mychat/chat/Taylor" com.simpleapp

Screen tracking and analytics

這個實例中展示怎么做屏幕追蹤并且發(fā)到Google Analytics.這個方法應(yīng)用在其他的移動分析SDK也是可以的.

Screen tracking

當(dāng)我們使用內(nèi)建的navigation container,我們使用onNavigationStateChange來追蹤screen.

 import { GoogleAnalyticsTracker } from 'react-native-google-analytics-bridge';

const tracker = new GoogleAnalyticsTracker(GA_TRACKING_ID);

// gets the current screen from navigation state
function getCurrentRouteName(navigationState) {
  if (!navigationState) {
    return null;
  }
  const route = navigationState.routes[navigationState.index];
  // dive into nested navigators
  if (route.routes) {
    return getCurrentRouteName(route);
  }
  return route.routeName;
}

const AppNavigator = StackNavigator(AppRouteConfigs);

export default () => (
  <AppNavigator
    onNavigationStateChange={(prevState, currentState) => {
      const currentScreen = getCurrentRouteName(currentState);
      const prevScreen = getCurrentRouteName(prevState);

      if (prevScreen !== currentScreen) {
        // the line below uses the Google Analytics tracker
        // change the tracker here to use other Mobile analytics SDK.
        tracker.trackScreenView(currentScreen);
      }
    }}
  />
);

使用Redux做Screen tracking

使用Redux的時候,我們可以寫Redux 中間件來track screen.為了達(dá)到這個目的,我們從前面的部分重新使用getCurrenRouteName.

 import { NavigationActions } from 'react-navigation';
import { GoogleAnalyticsTracker } from 'react-native-google-analytics-bridge';

const tracker = new GoogleAnalyticsTracker(GA_TRACKING_ID);

const screenTracking = ({ getState }) => next => (action) => {
  if (
    action.type !== NavigationActions.NAVIGATE
    && action.type !== NavigationActions.BACK
  ) {
    return next(action);
  }

  const currentScreen = getCurrentRouteName(getState().navigation);
  const result = next(action);
  const nextScreen = getCurrentRouteName(getState().navigation);
  if (nextScreen !== currentScreen) {
    // the line below uses the Google Analytics tracker
    // change the tracker here to use other Mobile analytics SDK.
    tracker.trackScreenView(nextScreen);
  }
  return result;
};

export default screenTracking;

創(chuàng)建Redux store并應(yīng)用上面的中間件

在創(chuàng)建store的時候應(yīng)用這個screenTracking的中間件.看看Redux Integration了解細(xì)節(jié).

 const store = createStore(
  combineReducers({
    navigation: navigationReducer,
    ...
  }),
  applyMiddleware(
    screenTracking,
    ...
    ),
);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容