《React Native 精解与实战》书籍连载「React Native 源码学习方法及其他资源」
此系列文章将整合我的 React 视频教程与 React Native 书籍中的精华部分,给大家介绍 React Native 源码学习方法及其他资源。
最后的章节给大家介绍 React Native 源码的查阅方法,以便你进行更加高阶的开发与研究时参阅,并分享了开发过程中可能遇到的众多问题的解决方案,以及与 React Native 开发相关、本书相关的一些线上资源。
15.6 React Native 源码剖析
我们在学习了 React Native 开发的方方面面之后,我们再次回到 React Native 的本质,给大家简要介绍 React Native 源码的学习方法,对 React Native 源码的整体框架做一个简单介绍,后续如果大家想深入阅读 React Native 框架的源码,希望这部分对你有所帮助,并且能从源码中学习到复杂框架的设计思想,希望大家也能“造出复杂的轮子”。
React Native 项目的 GitHub 地址为:https://github.com/facebook/react-native,源码的基本结构如图 A-1 所示。

图 A-1 React Native 源码结构
- 根目录中主要包含了项目的一些配置文件和一些描述性文档;
- 初始化项目的 React Native CLI 定义在 react-native-cli 文件夹下;
- RNTester 文件夹包含了 React Native 项目的单元测试用例以及组件、API 的使用示例代码,是一个学习 React Native 组件与 API 使用方法的宝库,这个在之前的章节有过介绍;
- React 文件夹是 iOS 原生平台的项目文件夹,用于与 React Native 的 JavaScript 代码通信;
- ReactAndroid 文件夹是 Android 原生平台的项目文件夹,用于与 React Native 的 JavaScript 代码通信;
- babel-preset 文件夹是 React Native 项目的 Babel 预配置;
- Libraries 文件夹是 React Native 源码的核心,所有的 React Native 组件与 API 的实现都在此文件夹中。
接下来我们就随便找一个组件来看看 React Native 是如何进行实现的,假设我们就来看看 Alert 组件的实现,其实通过我们在 React Native 与原生平台混合开发章节的学习,我们已经大概知道了 React Native 是如何来实现的。
我们先来看 Alert 组件 JavaScript 端的实现,Alert 组件包含的文件如图 A-2 所示。

图 A-2 Alert 组件源码结构
源码在 https://github.com/facebook/react-native/blob/master/Libraries/Alert/Alert.js。
1. ......
2. class Alert {
3.
4. /**
5. * Launches an alert dialog with the specified title and message.
6. *
7. * See http://facebook.github.io/react-native/docs/alert.html#alert
8. */
9. static alert(
10. title: ?string,
11. message?: ?string,
12. buttons?: Buttons,
13. options?: Options,
14. type?: AlertType,
15. ): void {
16. if (Platform.OS === 'ios') {
17. if (typeof type !== 'undefined') {
18. console.warn('Alert.alert() with a 5th "type" parameter is deprecated and will be removed. Use AlertIOS.prompt() instead.');
19. AlertIOS.alert(title, message, buttons, type);
20. return;
21. }
22. AlertIOS.alert(title, message, buttons);
23. } else if (Platform.OS === 'android') {
24. AlertAndroid.alert(title, message, buttons, options);
25. }
26. }
27. }
28.
29. /**
30. * Wrapper around the Android native module.
31. */
32. class AlertAndroid {
33.
34. static alert(
35. title: ?string,
36. message?: ?string,
37. buttons?: Buttons,
38. options?: Options,
39. ): void {
40. var config = {
41. title: title || '',
42. message: message || '',
43. };
44.
45. if (options) {
46. config = {...config, cancelable: options.cancelable};
47. }
48. // At most three buttons (neutral, negative, positive). Ignore rest.
49. // The text 'OK' should be probably localized. iOS Alert does that in native.
50. var validButtons: Buttons = buttons ? buttons.slice(0, 3) : [{text: 'OK'}];
51. var buttonPositive = validButtons.pop();
52. var buttonNegative = validButtons.pop();
53. var buttonNeutral = validButtons.pop();
54. if (buttonNeutral) {
55. config = {...config, buttonNeutral: buttonNeutral.text || '' };
56. }
57. if (buttonNegative) {
58. config = {...config, buttonNegative: buttonNegative.text || '' };
59. }
60. if (buttonPositive) {
61. config = {...config, buttonPositive: buttonPositive.text || '' };
62. }
63. NativeModules.DialogManagerAndroid.showAlert(
64. config,
65. (errorMessage) => console.warn(errorMessage),
66. (action, buttonKey) => {
67. if (action === NativeModules.DialogManagerAndroid.buttonClicked) {
68. if (buttonKey === NativeModules.DialogManagerAndroid.buttonNeutral) {
69. buttonNeutral.onPress && buttonNeutral.onPress();
70. } else if (buttonKey === NativeModules.DialogManagerAndroid.buttonNegative) {
71. buttonNegative.onPress && buttonNegative.onPress();
72. } else if (buttonKey === NativeModules.DialogManagerAndroid.buttonPositive) {
73. buttonPositive.onPress && buttonPositive.onPress();
74. }
75. } else if (action === NativeModules.DialogManagerAndroid.dismissed) {
76. options && options.onDismiss && options.onDismiss();
77. }
78. }
79. );
80. }
81. }
82.
83. module.exports = Alert;
84. ......
此段代码省略了头部的相关内容,在代码的第 16 行通过 Platform 变量判断当前所运行的平台,如果是 iOS 平台,那么就调用 AlertIOS 文件中定义的代码,如果是 Android 平台就调用代码第 32 行定义的 AlertAndroid 用于实现对 Android 原生平台 Alert 的调用,注意代码的第 63 行,是不是和我们实战 React Native 与 Android 平台混合开发的实现一样?所以 React Native 的所有组件与 API 基本都是通过此种方法进行了封装后提供给了开发者,所以我们可以说 iOS 原生平台与 Android 原生平台具备的功能都可以通过封装后在 React Native 框架中使用。
对应的 Android 原生端的实现代码在:https://github.com/facebook/react-native/blob/26684cf3adf4094eb6c405d345a75bf8c7c0bf88/ReactAndroid/src/main/java/com/facebook/react/modules/dialog/DialogModule.java。
86. ......
87. @ReactMethod
88. public void showAlert(
89. ReadableMap options,
90. Callback errorCallback,
91. final Callback actionCallback) {
92. final FragmentManagerHelper fragmentManagerHelper = getFragmentManagerHelper();
93. if (fragmentManagerHelper == null) {
94. errorCallback.invoke("Tried to show an alert while not attached to an Activity");
95. return;
96. }
97.
98. final Bundle args = new Bundle();
99. if (options.hasKey(KEY_TITLE)) {
100. args.putString(AlertFragment.ARG_TITLE, options.getString(KEY_TITLE));
101. }
102. if (options.hasKey(KEY_MESSAGE)) {
103. args.putString(AlertFragment.ARG_MESSAGE, options.getString(KEY_MESSAGE));
104. }
105. if (options.hasKey(KEY_BUTTON_POSITIVE)) {
106. args.putString(AlertFragment.ARG_BUTTON_POSITIVE, options.getString(KEY_BUTTON_POSITIVE));
107. }
108. if (options.hasKey(KEY_BUTTON_NEGATIVE)) {
109. args.putString(AlertFragment.ARG_BUTTON_NEGATIVE, options.getString(KEY_BUTTON_NEGATIVE));
110. }
111. if (options.hasKey(KEY_BUTTON_NEUTRAL)) {
112. args.putString(AlertFragment.ARG_BUTTON_NEUTRAL, options.getString(KEY_BUTTON_NEUTRAL));
113. }
114. if (options.hasKey(KEY_ITEMS)) {
115. ReadableArray items = options.getArray(KEY_ITEMS);
116. CharSequence[] itemsArray = new CharSequence[items.size()];
117. for (int i = 0; i < items.size(); i ++) {
118. itemsArray[i] = items.getString(i);
119. }
120. args.putCharSequenceArray(AlertFragment.ARG_ITEMS, itemsArray);
121. }
122. if (options.hasKey(KEY_CANCELABLE)) {
123. args.putBoolean(KEY_CANCELABLE, options.getBoolean(KEY_CANCELABLE));
124. }
125.
126. UiThreadUtil.runOnUiThread(new Runnable() {
127. @Override
128. public void run() {
129. fragmentManagerHelper.showNewAlert(mIsInForeground, args, actionCallback);
130. }
131. });
132.
133. }
134. ......
我们可以通过如上代码看到整个 Android 端的 showAlert 实现完全就是我们平时进行 Android 原生开发的代码实现,而通过 React Native 的封装之后,可以轻松让开发者在前端通过 JavaScript 的代码调用原生平台的方法,还可以直接适配两个平台,这样的框架设计的确有魅力,源码也值得好好阅读。
以上主要是给大家把 React Native 源码的基本结构告诉大家,空闲时间大家可以多去阅读 React Native 的实现源码,希望能对你 React Native 的学习再多一些帮助。
关于源码学习过程中的任何问题都可以在本书的线上资源站点找到我的联系方式和我交流。
15.7 难题解决方法与 Issues 重要作用
任何开发语言的学习,即使相关的书籍讲解得再详细,也不能完全覆盖你在开发过程中遇到的种种问题,所以我们需要掌握一些查找疑难问题的基本方案。
关于大家在学习本书进行 React Native 开发的过程中,有几个建议遵循的原则与查找问题的方案供大家参考。
1. 不要纠结于 React Native 的版本问题
很多时候我们在学习时纠结于 React Native 版本更新后,自己已学习的知识是否会落后,从而频繁地在安装最新版本的 React Native 框架、以及解决新版本与老的学习代码冲突上浪费太多的时间。其实很多的前端框架的更新都比较激进,React 基本实现了两周版本一更新,而每次的版本升级肯定会导致和你既有的项目代码有稍许冲突的地方,而如果你花大量地时间去解决这些冲突没有太大的意义。
所以一般的建议是你固定一个版本的 React Native 进行学习,因为版本的更新一般都很小,你只需要专注于框架的使用学习,尽快通过代码实战掌握框架的基本使用,后期可以认真研究框架的底层实现原理,而后期的版本更新基本都不会离开你已掌握的框架知识,更不会与你理解的实现原理有太大出入。
2. 单个平台进行问题定位
React Native 的开发因为涉及到 iOS 平台与 Android 平台的适配,有时一个问题可能影响到了两个平台的表现,这时应该逐个平台突破,而不是两个平台来一起调试,反而会造成代码的逻辑混乱,如果需要在代码上强制分离逻辑调试,可以通过 Platform 变量判断当前是运行在哪个平台,进而编写特定的平台代码进行分离调试。
3. 善用官方的 Issues
React Native 因为源码就发布在 GitHub 上,所以你可以直接在 GitHub 项目页面上查找开发过程中遇到的问题,在 Issues 页面中已包含了近万个问题,基本上你使用过程中遇到的问题肯定有别人遇到过,所以要学会直接在 Issues 中查找问题的原因以及解决方案,实在找不到解决方案你还可以向 React Native 项目提交 Issue,并可以获得 React Native 开发团队的回复,我想应该没有人比 React Native 开发团队的人更了解 React Native 了吧,不过在提问前最好自己多动手查阅一遍所有的 Issues 是否已包含了你遇到的问题了。
React Native 的官方 Issues 地址为:https://github.com/facebook/react-native/issues,截图如图 A-3 所示。

图 A-3 React Native 官方 Issues 页面
15.8 书籍相关资源列表
本书配套源码的 GitHub 地址
包含书籍中所有标注的完整代码、代码片段等,所有的章节代码都进行了单独文件夹存放,方便查阅,后续关于本书的相关更新也在此 GitHub 中更新。
地址:https://github.com/ParryQiu/ReactNative-Book-DemoReact GitHub
地址:https://github.com/facebook/react/React Native 官网
地址:https://facebook.github.io/react-native/React Native GitHub
地址:https://github.com/facebook/react-nativeawesome-react-native GitHub
地址:https://github.com/jondot/awesome-react-native深入理解 React JS 中的 setState
地址:http://blog.parryqiu.com/2017/12/19/react_set_state_asynchronously/从源码的角度再看 React JS 中的 setState
地址:http://blog.parryqiu.com/2017/12/29/react-state-in-sourcecode/从源码的角度看 React JS 中批量更新 State 的策略(上)
地址:http://blog.parryqiu.com/2018/01/04/2018-01-04/从源码的角度看 React JS 中批量更新 State 的策略(下)
地址:http://blog.parryqiu.com/2018/01/08/2018-01-08/Node.js 官网
地址:https://nodejs.orgnpm 官网
地址:https://www.npmjs.com/Node.js 下载页面
地址:https://nodejs.org/en/download/Homebrew 官网
地址:https://brew.sh/官方 UI 示例 App
地址:https://github.com/facebook/react-native/tree/master/RNTesterreact-native-elements
地址:https://github.com/react-native-training/react-native-elementsreact-native-tab-navigator
地址:https://github.com/happypancake/react-native-tab-navigatorreact-native-navigation
地址:https://github.com/wix/react-native-navigationreact-native-keychain
地址:https://github.com/oblador/react-native-keychainreact-native-sensitive-info
地址:https://github.com/mCodex/react-native-sensitive-inforeact-native-image-picker
地址:https://github.com/react-community/react-native-image-pickerFetch API 文档
地址:https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_FetchAwesome React Native
地址:https://github.com/jondot/awesome-react-nativereact-native-open-share
地址:https://github.com/ParryQiu/react-native-open-share新浪微博开放平台
地址:http://open.weibo.com/微信开放平台
地址:https://open.weixin.qq.com/QQ 开放平台
地址:http://open.qq.com/React-Virgin
地址:https://github.com/Trixieapp/react-virginreact-native-pathjs-charts
地址:https://github.com/capitalone/react-native-pathjs-chartsreact-native-gifted-listview
地址:https://github.com/FaridSafi/react-native-gifted-listviewreact-native-vector-icons
地址:https://github.com/oblador/react-native-vector-iconsReact Native metro
地址:https://github.com/facebook/metroGenymotion
地址:https://www.genymotion.com/极光推送官网
地址:https://www.jiguang.cn/jpush-react-native
地址:https://github.com/jpush/jpush-react-native极光推送 iOS 证书设置向导
地址:https://docs.jiguang.cn/jpush/client/iOS/ios_cer_guide/Ape Tools
地址:http://apetools.webprofusion.com/tools/imagegorillaApp 图标生成工具
https://makeappicon.com/
http://ios.hvims.com/
https://romannurik.github.io/AndroidAssetStudio/react-native-code-push
地址:https://github.com/Microsoft/react-native-code-pushReact Native Issues
地址:https://github.com/facebook/react-native/issues以上的所有链接汇总页面
如果你觉得需要查阅以上的链接,手动在浏览器中输入太麻烦,你可以直接访问本书的线上所有链接汇总站点,在此站点中你可以看到以上的所有链接以及链接说明,直接点击即可访问、查阅,希望能帮助大家提高学习效率。
地址:http://rn.parryqiu.com
《React Native 精解与实战》书籍连载「React Native 源码学习方法及其他资源」的更多相关文章
- 《React Native 精解与实战》书籍连载「Android 平台与 React Native 混合开发」
此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...
- 《React Native 精解与实战》书籍连载「iOS 平台与 React Native 混合开发」
此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...
- 《React Native 精解与实战》书籍连载「配置 iOS 与 Android 开发环境」
此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...
- 《React Native 精解与实战》书籍连载「React Native 网络请求与列表绑定」
此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...
- 《React Native 精解与实战》书籍连载「React Native 中的生命周期」
此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...
- 《React Native 精解与实战》书籍连载「React Native 底层原理」
此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...
- 《React Native 精解与实战》书籍连载「Node.js 简介与 React Native 开发环境配置」
此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...
- 《React Native 精解与实战》书籍连载「React 与 React Native 简介」
此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...
- [书籍精读]《React Native精解与实战》精读笔记分享
写在前面 书籍介绍:本书由架构师撰写,包含ReactNative框架底层原理,以及与iOS.Android混合开发案例,精选了大量实例代码,方便读者快速学习.主要内容分为两大部分,第1部分" ...
随机推荐
- Servlet主要相关类核心类 容器调用的过程浅析 servlet解读 怎么调用 Servlet是什么 工作机制
WEB简介 Web项目 是 B/S结构 浏览器/服务器模式的 浏览器发起请求,服务器作出响应 请求的发起和响应使用HTTP协议进行通讯 所谓协议也就是一种固定格式 而Socket是应用 ...
- springmvc 项目完整示例08 前台页面以及知识点总结
至此已经基本测试成功了,我们稍作完善,让它成为一个更加完整的项目 我们现在重新规划下逻辑 两个页面 一个登录页面 一个欢迎页面 登陆页面输入账号密码,登陆成功的话,跳转登陆成功 欢迎页面 并且,更新用 ...
- VBA中使用正则的两种方式
第一种方式(需要引用VBScript RegularExpression 5.5类库) Option Explicit Sub RegularExpresstion()'方法块 Dim regex A ...
- oracle安装数据库中文乱码解决办法
解决办法1: Linux下安装Oracle11g中文乱码 Linux下安装Oracle11g,安装界面乱码问题解决方法: 解决安装时中文是"囗囗囗囗囗囗囗囗" 1.进入刚解压的da ...
- Uncaught SyntaxError: Invalid shorthand property initializer报错
出现这个错误一定是:把":"写成了"="号
- java SPI机制
1. SPI是Service Provider Interfaces的简称.根据Java的SPI规范,我们可以定义一个服务接口,具体的实现由对应的实现者去提供,即Service Provider(服务 ...
- 使用 CODING 进行 Spring Boot 项目的集成
本文作者:CODING 用户 - 高文 持续集成 (Continuous integration) 是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可 ...
- 优秀代码摘录片段一:LinkedList中定位index时使用折半思想
在LinkedList有一段小代码,实现的功能是,在链表中间进行插如,所以在插如的过程中会需要找到对应的index位置的node元素: 如果放在平时只为了实现功能而进行遍历查找,很多人会直接使用一个w ...
- python 图片在线转字符画预览
文章链接:https://mp.weixin.qq.com/s/yiFOmljhyalE8ssAgwo6Jw 关于python图片转字符画,相信大家都不陌生,经常出现在 n个超有趣的python项目中 ...
- 三、View的事件体系
1.View基础知识 1.1.什么是View View是Android中所有控件的基类.View是一种界面层的控件的一种抽象,代表了一个控件.除了View,还有ViewGroup,内部包含了许多个控件 ...