此系列文章将整合我的 React 视频教程与 React Native 书籍中的精华部分,给大家介绍 React Native 源码学习方法及其他资源。
此文是我的出版书籍《React Native 精解与实战》连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理、React Native 组件布局、组件与 API 的介绍与代码实战,以及 React Native 与 iOS、Android 平台的混合开发底层原理讲解与代码实战演示,精选了大量实例代码,方便读者快速学习。
***书籍配套视频教程「80 节实战课精通 React Native 开发」***:此视频课程建议配合书籍学习,书籍中原理性的东西讲解的比较清晰,而视频教程对于组件、API 等部分的代码实战开发讲解比较直观。
书籍所有相关资料请访问:http://rn.parryqiu.com
之前连载文章列表
「80节实战课精通 React Native 开发」视频课程大纲
React 与 React Native 简介
React Native 底层原理
Node.js 简介与 React Native 开发环境配置
React Native 中的生命周期
React Native 网络请求与列表绑定
配置 iOS 与 Android 开发环境
最后的章节给大家介绍 React Native 源码的查阅方法,以便你进行更加高阶的开发与研究时参阅,并分享了开发过程中可能遇到的众多问题的解决方案,以及与 React Native 开发相关、本书相关的一些线上资源。
我们在学习了 React Native 开发的方方面面之后,我们再次回到 React Native 的本质,给大家简要介绍 React Native 源码的学习方法,对 React Native 源码的整体框架做一个简单介绍,后续如果大家想深入阅读 React Native 框架的源码,希望这部分对你有所帮助,并且能从源码中学习到复杂框架的设计思想,希望大家也能“造出复杂的轮子”。
React Native 项目的 GitHub 地址为:https://github.com/facebook/react-native,源码的基本结构如图 A-1 所示。
接下来我们就随便找一个组件来看看 React Native 是如何进行实现的,假设我们就来看看 Alert 组件的实现,其实通过我们在 React Native 与原生平台混合开发章节的学习,我们已经大概知道了 React Native 是如何来实现的。
我们先来看 Alert 组件 JavaScript 端的实现,Alert 组件包含的文件如图 A-2 所示。
源码在 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 的学习再多一些帮助。
关于源码学习过程中的任何问题都可以在本书的线上资源站点找到我的联系方式和我交流。
任何开发语言的学习,即使相关的书籍讲解得再详细,也不能完全覆盖你在开发过程中遇到的种种问题,所以我们需要掌握一些查找疑难问题的基本方案。
关于大家在学习本书进行 React Native 开发的过程中,有几个建议遵循的原则与查找问题的方案供大家参考。
很多时候我们在学习时纠结于 React Native 版本更新后,自己已学习的知识是否会落后,从而频繁地在安装最新版本的 React Native 框架、以及解决新版本与老的学习代码冲突上浪费太多的时间。其实很多的前端框架的更新都比较激进,React 基本实现了两周版本一更新,而每次的版本升级肯定会导致和你既有的项目代码有稍许冲突的地方,而如果你花大量地时间去解决这些冲突没有太大的意义。
所以一般的建议是你固定一个版本的 React Native 进行学习,因为版本的更新一般都很小,你只需要专注于框架的使用学习,尽快通过代码实战掌握框架的基本使用,后期可以认真研究框架的底层实现原理,而后期的版本更新基本都不会离开你已掌握的框架知识,更不会与你理解的实现原理有太大出入。
React Native 的开发因为涉及到 iOS 平台与 Android 平台的适配,有时一个问题可能影响到了两个平台的表现,这时应该逐个平台突破,而不是两个平台来一起调试,反而会造成代码的逻辑混乱,如果需要在代码上强制分离逻辑调试,可以通过 Platform 变量判断当前是运行在哪个平台,进而编写特定的平台代码进行分离调试。
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 页面
本书配套源码的 GitHub 地址
包含书籍中所有标注的完整代码、代码片段等,所有的章节代码都进行了单独文件夹存放,方便查阅,后续关于本书的相关更新也在此 GitHub 中更新。
地址:https://github.com/ParryQiu/ReactNative-Book-Demo
React GitHub
地址:https://github.com/facebook/react/
React Native 官网
地址:https://facebook.github.io/react-native/
React Native GitHub
地址:https://github.com/facebook/react-native
awesome-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.org
npm 官网
地址: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/RNTester
react-native-elements
地址:https://github.com/react-native-training/react-native-elements
react-native-tab-navigator
地址:https://github.com/happypancake/react-native-tab-navigator
react-native-navigation
地址:https://github.com/wix/react-native-navigation
react-native-keychain
地址:https://github.com/oblador/react-native-keychain
react-native-sensitive-info
地址:https://github.com/mCodex/react-native-sensitive-info
react-native-image-picker
地址:https://github.com/react-community/react-native-image-picker
Fetch API 文档
地址:https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
Awesome React Native
地址:https://github.com/jondot/awesome-react-native
react-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-virgin
react-native-pathjs-charts
地址:https://github.com/capitalone/react-native-pathjs-charts
react-native-gifted-listview
地址:https://github.com/FaridSafi/react-native-gifted-listview
react-native-vector-icons
地址:https://github.com/oblador/react-native-vector-icons
React Native metro
地址:https://github.com/facebook/metro
Genymotion
地址: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/imagegorilla
App 图标生成工具
https://makeappicon.com/
http://ios.hvims.com/
https://romannurik.github.io/AndroidAssetStudio/
react-native-code-push
地址:https://github.com/Microsoft/react-native-code-push
React Native Issues
地址:https://github.com/facebook/react-native/issues
以上的所有链接汇总页面
如果你觉得需要查阅以上的链接,手动在浏览器中输入太麻烦,你可以直接访问本书的线上所有链接汇总站点,在此站点中你可以看到以上的所有链接以及链接说明,直接点击即可访问、查阅,希望能帮助大家提高学习效率。
地址:http://rn.parryqiu.com