摘要:每次都信誓旦旦的給自己立下要好好學習源碼的,結果都是因為某個地方卡住了,或是其他原因沒看多少就放棄了。這次又給自己立個堅持看完源碼。我看的源碼版本是。本篇文章是官方文檔里邊的一篇文章的翻譯,原文地址。
每次都信誓旦旦的給自己立下要好好學習react源碼的flag,結果都是因為某個地方卡住了,或是其他原因沒看多少就放棄了。這次又給自己立個flag-堅持看完react源碼。為了敦促自己,特開設這樣一個專欄來記錄自己的學習歷程,這意味著這個專欄的文章質量并不高,你可以拿來參考參考,切莫全信,我不想誤人子弟,后面要是學有所成再考慮產出些好點的文章。 要是發現文章中有什么不當之處,歡迎批評交流。我看的源碼版本是16.8.2。
為了看react源碼,我查找了不少資料,這里推薦兩個參考資料,個人覺得寫得不錯。
慕課網一個課的電子書,他有個源碼解析的視頻教程,應該不錯,不過我沒買。
一個知乎專欄,寫得很清晰,只不過是15.6.2的, 在react16里面一些方法找不到了。
本篇文章是官方文檔里邊的一篇文章的翻譯,原文地址。
這部分將給你介紹下react代碼的基本結構, 代碼約定和它的基本實現.
如果你想為react貢獻代碼的話, 我們希望這篇指南能讓你寫代碼更加舒服.
我們不推薦將這些約定用在react應用中, 因為這些約定大多是基于一些歷史原因存在的, 隨著時間推移可能會發生變化.
外部依賴react 幾乎沒有外部依賴. 通常require()指向的是react自己代碼庫的一個文件. 但是也有一些例外.
由于react想要通過庫共享一些諸如Relay的小工具, 所以存在fbjs repository , 而且我們讓他們是同步的. 我們沒有依賴任何node生態系統下的小模塊, 因為我們希望facebook的工程師的能能再任何必要的時候修改他們. fbjs中的任何工具都不能被認為是公共api, 并且他們只是為Facebook的一些工程使用, 比如react.
一級目錄克隆了react的倉庫后你會發現在里邊有幾個一級目錄.
packages目錄包括一些元數據(如package.json)和react庫提供的所有包的源碼(src的下面), 如果你想修改代碼, src下面就是你要花時間最多的地方.
fixtures目錄包括了為貢獻者準備的一些小的react的測試應用
build是react打包輸出的目錄. 他不在代碼庫管理范疇, 但是當你第一次打包后就會生成.
文檔是放在和react不同的另一個倉庫管理的.
還有一些其他一級目錄, 他們大多是工具層面的, 在你貢獻代碼時可能不會用到他們能.
共同測試(Colocated Tests)我們沒有搞個一級目錄來做單元測試. 我們把它放在了被測試文件相鄰的被稱為__tests__的目錄.
舉個例子, 對于setInnerHTML.js這個文件的測試被放在與他同級的__tests__/setInnerHTML-test.js這個里邊.
這個詞不知道怎么翻譯
Warnings and Invariantsreact中使用warning模塊顯示警告信息.
var warning = require("warning"); warning( 2 + 2 === 4, "Math is not working today." );
當警告條件是false的時候會展示警告信息
可以這么理解, 條件應該指示正常的情況, 而不是異常的情況. 就是說第一個參數是true表示的是正常, false是異常.
最好避免使用console取代warnings.
var warning = require("warning"); var didWarnAboutMath = false; if (!didWarnAboutMath) { warning( 2 + 2 === 4, "Math is not working today." ); didWarnAboutMath = true; }
警告只會在開發模式被開啟. 生產環境下被去掉了. 如果你想阻止某些代碼塊的執行, 那么你可以用invariant模塊.
var invariant = require("invariant"); invariant( 2 + 2 === 4, "You shall not pass!" );
當條件為false時, 這個方法會直接拋出異常.
“Invariant” 就是說這個條件為真, 你可以認為他就是做了個斷言.
保持開發環境和生產環境一致是很重要的, 因此invariant在生產環境和開發環境都可以拋出異常. 生產環境下的錯誤消息被自動替換成錯誤碼, 以防增加代碼體積.
Development and Production你可以使用__DEV__這個為全局變量指定僅僅在開發環境才執行的代碼塊.
他是在編譯過程中工作的, 他是在commonjs編譯的時候檢查process.env.NODE_ENV !== "production"這個值.
多帶帶編譯的時候, 他在未壓縮版是true, 在壓縮版直接被去掉了.
if (__DEV__) { // 這里邊的代碼只會帶開發環境執行 }Flow
我們最近開始引入flow做靜態類型檢查, 在文件頭的注釋里標注了@flow的使用了類型檢查.
我們接受在現有代碼加入flow類型檢查的pull request (不錯哎, 可以試著提個pull request哦). Flow的簽名類似下面這樣.
ReactRef.detachRefs = function( instance: ReactInstance, element: ReactElement | string | number | null | false, ): void { // ... }
時機成熟的時候, 新代碼要用Flow 簽名, 你可以在本地運行yarn flow用Flow檢查你的代碼.
動態植入react在一些模塊使用了動態植入. 但是這個東西不太好, 因為他讓代碼比較難理解了. 他存在的理由是react一開始只把支持dom作為目標的. 但是后來殺出了個React Native, 他是基于react的, 我們不得不加入動態植入好讓react native 重載一些行為.
你可能會看到模塊像下面這樣聲明它的動態依賴
// Dynamically injected var textComponentClass = null; // Relies on dynamically injected value function createInstanceForText(text) { return new textComponentClass(text); } var ReactHostComponent = { createInstanceForText, // Provides an opportunity for dynamic injection injection: { injectTextComponentClass: function(componentClass) { textComponentClass = componentClass; }, }, }; module.exports = ReactHostComponent;
注入的部分沒有以任何方式特殊處理. 但是規定, 它的意思是這個模塊想在運行時有一些依賴(可能是平臺特定的)被注入進去.
代碼里邊有幾個注入的入口. 未來, 我們將廢棄掉這種動態植入的機制, 方案是在編譯時以靜態方式處理他們.
多包react是個monorepo, 他的倉庫包含了多個獨立的包, 因此他們的修改可以合在一起, 而且issues也可以放在一個地方.
React核心react的核心是所有頂級api, 包括:
React.createElement()
React.Component
React.Children
react核心只包括定義組件必要的api, 并不包括reconciliation算法和平臺特定代碼. React DOM和React Native都使用了他們.
react核心的相關代碼在packages/react里邊. npm使用時在react這個包里邊, 瀏覽器版的是react.js, 他掛載一個被稱為React的全局變量.
Renderersreact起初是為DOM創造的, 但是后臺通過RN被用來支持原生環境了. 這里介紹加react內部的“renderers”的理念.
“renderers”管理了react樹如何變成平臺可調用的東西.
Renderers也在packages里邊
React DOM Renderer 把react 組件渲染進 DOM. 他實現了頂級的ReactDOM APIs, 在react-dom這個npm包里被暴露出來. 瀏覽器版叫react-dom.js, 通過ReactDOM這個全局變量暴露出來.
React Native Renderer把react組件渲染到原生視圖層里. 他被RN內部使用.
React Test Renderer 把react組件渲染成JSON樹, 他被Jest的一個特性Snapshot Testing使用, 在react-test-renderer這個npm包里可用.
另一個官方唯一支持的渲染器是react-art, 他曾經是個獨立的庫, 現在被移進來了.
注意
技術上react-native-renderer是很薄的一層, 只是用來和RN的實現相互配合, 真正的平臺相關代碼是RN庫里一些native view.Reconcilers(協調器)
相當多的渲染器, 如Reat DOM, React Native 需要共享一套邏輯. 尤其reconciliation算法需要足夠的相似, 以便讓rendering, 自定義組件, 狀態, 生命周期函數和refs能跨平臺工作.
為了解決這個問題, 不同的渲染器共用一些代碼. 我們把React 中的這個部分叫做"reconciler". 當一個更新比如setState要執行了,Reconcilers就去在組件上調用render(), 然后mounts, updates, 或者unmounts他們.
Reconcilers沒有獨立成包, 因為他現在還沒有公共API. 相反, 他僅僅是在渲染器被使用, 比如React DOM , React Native.
Stack ReconcilerStack Reconciler 是在react15之前實現使用的, 現在已經不用了, 但是下一部分的文檔還會有詳細的介紹.
Fiber Reconciler"Fiber"是為了解決stack reconciler固有問題和修復長期存在的bug所做的努力, 他從react16開始成為默認的Reconciler.
他的主要目標是:
在chunks里分離可中斷的工作
在過程中重建, 重用work或者改變他的優先級(瞎翻譯的)的能力
在父子組件前進或回退以只是react中的布局的能力
在render方法里返回多個元素的能力
更好的支持錯誤邊際
你可在這里和這里閱讀更多關于Fiber架構的相關信息. 但是React16對他做了封裝, 默認不支持異步特性了.
他的源碼在packages/react-reconciler里邊.
事件系統react實現了一個對renders透明的事件系統, 這個系統被用于react dom 和react native. 源碼在packages/events;
這里有個視頻https://www.youtube.com/watch?v=dRo_egw7tBc
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99854.html
摘要:寫在前面的模板非常多,上有著各種各樣的免費及付費模板。概述是一個基于設計的自適應多用途的管理后臺模板。下一篇之模板的學習之路源碼分析之部分 寫在前面 bootstrap 的模板非常多,Envato 上有著各種各樣的免費及付費模板。Metronic 是我最喜歡的模板之一(看一眼就喜歡上的那種),當前售價 $28 ,覺得贊的,不妨支持一下作者。覺得貴的,想必不用我說,你也會找到途徑。:b ...
摘要:期間我也參考了上的一些項目,有的代碼雖然簡單,但是并沒有開發講解,對新手來說確實不友好。所以我想趁著這個機會,在寫代碼做項目的時候做一套開發教程講解,讓新手也能順利上路。后端是選用項目有后臺管理系統線上業務系統,全方位支持企業業務流程。 一 前言 關于這一系列文章的由來,我要做一個詳細的說明,這些都在正文里面。關于代碼的托管地址,請戳這里:GitHub關于開源代碼的使用:免費用于個人、...
摘要:期間我也參考了上的一些項目,有的代碼雖然簡單,但是并沒有開發講解,對新手來說確實不友好。所以我想趁著這個機會,在寫代碼做項目的時候做一套開發教程講解,讓新手也能順利上路。后端是選用項目有后臺管理系統線上業務系統,全方位支持企業業務流程。 一 前言 關于這一系列文章的由來,我要做一個詳細的說明,這些都在正文里面。關于代碼的托管地址,請戳這里:GitHub關于開源代碼的使用:免費用于個人、...
摘要:期間我也參考了上的一些項目,有的代碼雖然簡單,但是并沒有開發講解,對新手來說確實不友好。所以我想趁著這個機會,在寫代碼做項目的時候做一套開發教程講解,讓新手也能順利上路。后端是選用項目有后臺管理系統線上業務系統,全方位支持企業業務流程。 一 前言 關于這一系列文章的由來,我要做一個詳細的說明,這些都在正文里面。關于代碼的托管地址,請戳這里:GitHub關于開源代碼的使用:免費用于個人、...
閱讀 3226·2021-10-13 09:40
閱讀 3688·2019-08-30 15:54
閱讀 1309·2019-08-30 13:20
閱讀 2993·2019-08-30 11:26
閱讀 475·2019-08-29 11:33
閱讀 1099·2019-08-26 14:00
閱讀 2356·2019-08-26 13:58
閱讀 3366·2019-08-26 10:39