《React Native 精解與實戰》書籍連載「React Native 源碼學習方法及其餘資源」

此係列文章將整合個人 React 視頻教程與 React Native 書籍中的精華部分,給你們介紹 React Native 源碼學習方法及其餘資源。html

此文是個人出版書籍《React Native 精解與實戰》連載分享,此書由機械工業出版社出版,書中詳解了 React Native 框架底層原理、React Native 組件佈局、組件與 API 的介紹與代碼實戰,以及 React Native 與 iOS、Android 平臺的混合開發底層原理講解與代碼實戰演示,精選了大量實例代碼,方便讀者快速學習。前端

***書籍配套視頻教程「80 節實戰課精通 React Native 開發」***:此視頻課程建議配合書籍學習,書籍中原理性的東西講解的比較清晰,而視頻教程對於組件、API 等部分的代碼實戰開發講解比較直觀。java

書籍全部相關資料請訪問:rn.parryqiu.comnode

以前連載文章列表 「80節實戰課精通 React Native 開發」視頻課程大綱react

React 與 React Native 簡介android

React Native 底層原理ios

Node.js 簡介與 React Native 開發環境配置git

React Native 中的生命週期github

React Native 網絡請求與列表綁定web

配置 iOS 與 Android 開發環境

最後的章節給你們介紹 React Native 源碼的查閱方法,以便你進行更加高階的開發與研究時參閱,並分享了開發過程當中可能遇到的衆多問題的解決方案,以及與 React Native 開發相關、本書相關的一些線上資源。

15.6 React Native 源碼剖析

咱們在學習了 React Native 開發的方方面面以後,咱們再次回到 React Native 的本質,給你們簡要介紹 React Native 源碼的學習方法,對 React Native 源碼的總體框架作一個簡單介紹,後續若是你們想深刻閱讀 React Native 框架的源碼,但願這部分對你有所幫助,而且能從源碼中學習到複雜框架的設計思想,但願你們也能「造出複雜的輪子」。

React Native 項目的 GitHub 地址爲:github.com/facebook/re…,源碼的基本結構如圖 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 組件源碼結構

源碼在 github.com/facebook/re…

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 原生端的實現代碼在:github.com/facebook/re…

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 地址爲:github.com/facebook/re…,截圖如圖 A-3 所示。

截圖
圖 A-3 React Native 官方 Issues 頁面

15.8 書籍相關資源列表

  1. 本書配套源碼的 GitHub 地址 包含書籍中全部標註的完整代碼、代碼片斷等,全部的章節代碼都進行了單獨文件夾存放,方便查閱,後續關於本書的相關更新也在此 GitHub 中更新。 地址:github.com/ParryQiu/Re…

  2. React GitHub 地址:github.com/facebook/re…

  3. React Native 官網 地址:facebook.github.io/react-nativ…

  4. React Native GitHub 地址:github.com/facebook/re…

  5. awesome-react-native GitHub 地址:github.com/jondot/awes…

  6. 深刻理解 React JS 中的 setState 地址:blog.parryqiu.com/2017/12/19/…

  7. 從源碼的角度再看 React JS 中的 setState 地址:blog.parryqiu.com/2017/12/29/…

  8. 從源碼的角度看 React JS 中批量更新 State 的策略(上) 地址:blog.parryqiu.com/2018/01/04/…

  9. 從源碼的角度看 React JS 中批量更新 State 的策略(下) 地址:blog.parryqiu.com/2018/01/08/…

  10. Node.js 官網 地址:nodejs.org

  11. npm 官網 地址:www.npmjs.com/

  12. Node.js 下載頁面 地址:nodejs.org/en/download…

  13. Homebrew 官網 地址:brew.sh/

  14. 官方 UI 示例 App 地址:github.com/facebook/re…

  15. react-native-elements 地址:github.com/react-nativ…

  16. react-native-tab-navigator 地址:github.com/happypancak…

  17. react-native-navigation 地址:github.com/wix/react-n…

  18. react-native-keychain 地址:github.com/oblador/rea…

  19. react-native-sensitive-info 地址:github.com/mCodex/reac…

  20. react-native-image-picker 地址:github.com/react-commu…

  21. Fetch API 文檔 地址:developer.mozilla.org/en-US/docs/…

  22. Awesome React Native 地址:github.com/jondot/awes…

  23. react-native-open-share 地址:github.com/ParryQiu/re…

  24. 新浪微博開放平臺 地址:open.weibo.com/

  25. 微信開放平臺 地址:open.weixin.qq.com/

  26. QQ 開放平臺 地址:open.qq.com/

  27. React-Virgin 地址:github.com/Trixieapp/r…

  28. react-native-pathjs-charts 地址:github.com/capitalone/…

  29. react-native-gifted-listview 地址:github.com/FaridSafi/r…

  30. react-native-vector-icons 地址:github.com/oblador/rea…

  31. React Native metro 地址:github.com/facebook/me…

  32. Genymotion 地址:www.genymotion.com/

  33. 極光推送官網 地址:www.jiguang.cn/

  34. jpush-react-native 地址:github.com/jpush/jpush…

  35. 極光推送 iOS 證書設置嚮導 地址:docs.jiguang.cn/jpush/clien…

  36. Ape Tools 地址:apetools.webprofusion.com/tools/image…

  37. App 圖標生成工具 makeappicon.com/ ios.hvims.com/ romannurik.github.io/AndroidAsse…

  38. react-native-code-push 地址:github.com/Microsoft/r…

  39. React Native Issues 地址:github.com/facebook/re…

  40. 以上的全部連接彙總頁面 若是你以爲須要查閱以上的連接,手動在瀏覽器中輸入太麻煩,你能夠直接訪問本書的線上全部連接彙總站點,在此站點中你能夠看到以上的全部連接以及連接說明,直接點擊便可訪問、查閱,但願能幫助你們提升學習效率。 地址:rn.parryqiu.com

相關文章
相關標籤/搜索