已经有段时间没有写 RN, 之前用 Navigation 还是 2.x 版本, 现在已经 6.x .
看到RN 官方有这一段:
This native-stack navigator uses the native APIs:
UINavigationController
on iOS andFragment
on Android so that navigation built withcreateNativeStackNavigator
will behave the same and have the same performance characteristics as apps built natively on top of those APIs.
比较疑惑, RN 不是只有一个 RootView 吗? (rootViewController.view = rootView
)
之前页面跳转(RN 里面)都是 Navigation 库给做的转场动画, 现在 它是怎么实现的用原生的 API 来做跳转?
猜测: ViewController 如果没有原生的 Navigation 只能 present, 不能 push/pop; 所以应该是做了某些魔法操作, 当用户使用 native-stack
的情况下, 在原生里添加的一层 Navigation.
但具体是怎么做的呢?
1
Bijiabo 2022-02-13 16:56:53 +08:00
将 NavigationController 的 View 作为 child view ,可以仔细分析一下 react-native-screens 中的 `RNSScreenStack.m`
在 SDK 中将继承自 `UINavigationController` 的 `RNScreensNavigationController` 作为原生导航管理用途,将 RNScreensNavigationController 的 View 作为 RNSScreenNavigationContainer 的 Native UI Component 的子 View ,大概是这样的。 |
2
FaiChou OP @Bijiabo 谢谢回复. 还是有几个问题:
``` RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"AwesomeProject" initialProperties:nil]; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [UIViewController new]; rootViewController.view = rootView; self.window.rootViewController = rootViewController; ``` 这是使用 RN 创建的项目, 里面只有一个 rootViewController. 它是如何(在哪里)实现 `将 NavigationController 的 View 作为 child view` 的? 是不是在编译 .h .m 时候给替换掉了? 具体是怎么完成的? 在 js 里写了很多 view, 使用原生的 navigation 跳转新的页面, 数据传输不会有影响吧? RN 的 js 那边都是一个 runtime, 比如要 push 新的页面, 在原生端得有一个 Controller 的生命周期, didLoad 后再将 RN 的 view 设置为它的 view? 还需要 bridge 来获取 RN 的 view 吗? |
3
Bijiabo 2022-02-13 19:43:14 +08:00 1
@FaiChou
关于这个问题: 这是使用 RN 创建的项目, 里面只有一个 rootViewController. 它是如何(在哪里)实现 `将 NavigationController 的 View 作为 child view` 的? 是不是在编译 .h .m 时候给替换掉了? 具体是怎么完成的? 看到你的问题顺手看了一下 react-native-screens ,目前初步判断是这样的,可能不够准确。可以在 `RNSScreenStack.m` 中看到: - 具体实现应该是对应此文件 249 行的 `[self addSubview:controller.view];` - 这个 Native UI Component 封装实现了 `- (void)insertReactSubview:(RNSScreenView *)subview atIndex:(NSInteger)atIndex` 这个方法,可以拿到 JSX 中嵌套的子组件,渲染在 UINavigationController 中的子 controller 中 ------ 数据传输应该不会受到影响,目前还没遇到这方面的明显问题。看到现在新的 Fabric 布局引擎是基于 JSI 来做通讯的,不需要通过走 Bridge 的方式复制大量数据了。 关于生命周期这块不是看的很清楚(没仔细看,先做家务去 T_T...),应该是在 Native UI Component 首次渲染的时候设定为 child view 的。 |