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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...