react源碼總覽(翻譯)

来源:https://www.cnblogs.com/floor/archive/2018/12/10/10094323.html
-Advertisement-
Play Games

用react也有段時間了, 是時候看看人家源碼了. 看源碼之前看到官方文檔有這麼篇文章介紹其代碼結構了, 為了看源碼能順利些, 遂決定將其翻譯來看看, 小弟英語也是半瓢水, 好多單詞得查詞典, 不當之處請批評. 直接從字面翻譯的, 後面看源碼後可能會在再修改下. ...


用react也有段時間了, 是時候看看人家源碼了. 看源碼之前看到官方文檔 有這麼篇文章介紹其代碼結構了, 為了看源碼能順利些, 遂決定將其翻譯來看看, 小弟英語也是半瓢水, 好多單詞得查詞典, 不當之處請批評. 直接從字面翻譯的, 後面看源碼後可能會在再修改下.


下麵是翻譯

這部分將給你介紹下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 Invariants

react中使用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的全局變數.

Renderers

react起初是為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 Reconciler

Stack 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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 2018/12/6 星期四 19:34:07 authot by dabaine 資料庫註釋; 這就是註釋 / ..... / 這也是註釋 創建庫; create databse [if not exists] dabaine [character set "utf8"]; 查看所有資料庫; sho ...
  • 阿裡雲限時紅包領取,雲產品通用紅包,可疊加官網常規優惠,最高1888 內部鏈接 https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=up4l93vp ...
  • 一、庫操作 二、表操作 1,存儲引擎 存儲引擎就是表的類型,MySQL中根據不同的存儲引擎會有不同的處理機制,存儲引擎的概念是MySQL裡面才有的。 1.1,MySQL的一個整個工作流程 1.2,存儲引擎的分類 在cmd中輸入show engines可以查看所有的引擎,輸入show variable ...
  • 問題:新安裝的資料庫,訪問的時候後臺報錯找不表,發現是數據查詢語句對大小寫敏感. 1.關閉MySQL服務 2.在服務運行目錄找到my.ini或者my.cnf文件 打開文件, 3.找到[mysqld]在下麵增加一行 4.lower_case_table_names=1 (0:大小寫敏感;1:大小寫不敏 ...
  • 1. 資料庫表 1.1 員工表 1.2 部門表 1.3 工作表 1.4 位置表 2. 基礎查詢(select) 2.1 查詢單個欄位 2.2 查詢多個欄位 2.3 查詢所有欄位 2.4 查詢常量值、表達式 2.5 查詢函數 2.6 起別名(如果查詢的欄位有重名,可以使用起別名區分,別名中有特殊符號, ...
  • 從六號開始搞Flutter,到今天寫這篇blog已經過了4天時間,文檔初步瀏覽了一遍,寫下了這個demo。demo源碼分享在github上,現在對flutter有種說不出的喜歡了。大家一起搞吧! 廢話不多說,開始不如正題: 一:單擊,雙擊,長按->傳動的手勢效果,另外這裡用來Fluttertoast ...
  • 流程介紹 1. 使用 網路框架進行 請求,獲得 數據 //一個封裝好的工具類的靜態方法 public static void sendOkHttpRequest(final String address, final okhttp3.Callback callback) { OkHttpClient ...
  • 文章鏈接: "https://mp.weixin.qq.com/s/1gkMtLu0BTXOUOj6isDjUw" 日常android開發過程中,會遇到編輯框輸入內容彈出軟鍵盤,往往會出現鍵盤遮擋內容,或者出現頁面整體上移的,或多或少在體驗上都不是很優雅,今天提供個方法是自行控制頁面上移距離,竟可能 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...