一、前言
React Native 是由 Facebook 推出的移动应用开发框架,可以用来开发 iOS、Android、Web 等跨平台应用程序,官网为:https://facebook.github.io/react-native/。
React Native 和传统的 Hybrid 应用最大的区别就是它抛开了 WebView 控件。React Native 产出的并不是 “网页应用”、“HTML5 应用” 或者 “混合应用”,而是一个真正的移动应用,从使用感受上和用 Objective-C 或 Java 编写的应用相比几乎是没有区别的。React Native 所使用的基础 UI 组件和原生应用完全一致。我们要做的就是把这些基础组件使用 JavaScript 和 React 的方式组合起来。React Native 是一个非常优秀的跨平台框架。
React Native 可以通过自定义 Module[1] 的方式实现 JavaScript 调用 Native 接口,神策分析的 React Native Module[2] 使用新方案实现了 React Native 全埋点功能。
本文以 Android 项目为例,介绍了神策分析 React Native Module 是如何通过 React Navigation 来实现全埋点的页面浏览事件采集。
二、React Navigation
2.1 简介
React Navigation 的诞生源于 React Native 社区对基于 JavaScript 的导航组件可扩展和易用性的需求。
React Navigation 是 Facebook,Expo 和 React 社区的开发者们合作的结果:它取代并改进了 React Native 生态系统中的多个导航库,包括 Ex-Navigation、React Native 的 Navigator 和 NavigationExperimental 组件。
2.2 安装
下面以 npm 方式为例介绍下 React Navigation 的安装流程:
1. 导入必需包
在 React Native 项目中安装 React Navigation 包:
npm install @react-navigation/native
在 React Native 项目中安装依赖包:
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
2. 导入可选包
React Navigation 支持三种类型的导航器,分别是 StackNavigator[3]、TabNavigator[4] 和 DrawerNavigator[5]。
StackNavigator
一次只渲染一个页面,并提供页面之间跳转的方法。当打开一个新的页面时,它被放置在堆栈的顶部。
引入方式如下:
npm install @react-navigation/stack
TabNavigator
渲染一个选项卡,让用户可以在几个页面之间切换。
引入方式:
npm install @react-navigation/bottom-tabs
DrawerNavigator
提供一个从屏幕左侧滑入的抽屉。
引入方式:
npm install @react-navigation/drawer
2.3 使用方式
通过 NavigationContainer 包裹需要使用的导航器 Stack.Navigator、Tab.Navigator、Drawer.Navigator,如下所示:
-----------------------------Stack------------------------------------
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Store" component={StoreScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
----------------------------Tab-------------------------------------
const Tab = createBottomTabNavigator();
function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Store" component={StoreScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
-----------------------------Drawer------------------------------------
const Drawer = createDrawerNavigator();
function App() {
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Store" component={StoreScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
三、具体实现
因为 React Native 项目无法从系统层级标识页面,所以通过 React Navigation 的 RouteName 来进行页面的唯一标识。
3.1 NavigationContainer 解析
3.1.1. BaseNavigationContainer
所有的导航都包裹在 NavigationContainer 中,其中 BaseNavigationContainer 通过 React.useEffect[6] 监听了 state:
BaseNavigationContainer
const BaseNavigationContainer = React.forwardRef(