react 源碼概覽

React 采用 monorepo 的管理方式。倉庫中包含多個(gè)獨(dú)立的包,以便于更改可以一起聯(lián)調(diào),并且問題只會(huì)出現(xiàn)在同一地方。
react
React “Core” 中包含所有全局 React API,比如:
1、React.createElement()
2、React.Component
3、React.Children
React 核心只包含定義組件必要的 API。它不包含協(xié)調(diào)算法或者其他平臺(tái)特定的代碼。它同時(shí)適用于 React DOM 和 React Native 組件。
React 核心代碼在源碼的 packages/react 目錄中。在 npm 上發(fā)布為 react 包。相應(yīng)的獨(dú)立瀏覽器構(gòu)建版本稱為 react.js,它會(huì)導(dǎo)出一個(gè)稱為 React 的全局對(duì)象。
import React from 'react';class Welcome extends React.Component {render() {return <h1>Hello, {this.props.name}h1>;}}
react-dom
React 最初只是服務(wù)于 DOM,但是這之后被改編成也能同時(shí)支持原生平臺(tái)的 React Native。因此,在 React 內(nèi)部機(jī)制中引入了“渲染器”這個(gè)概念。
渲染器用于管理一棵 React 樹,使其根據(jù)底層平臺(tái)進(jìn)行不同的調(diào)用。
渲染器同樣位于 packages/ 目錄下:
React DOM Renderer 將 React 組件渲染成 DOM。它實(shí)現(xiàn)了全局 ReactDOMAPI,這在npm上作為 react-dom 包。這也可以作為單獨(dú)瀏覽器版本使用,稱為 react-dom.js,導(dǎo)出一個(gè) ReactDOM 的全局對(duì)象.
import ReactDOM from 'react-dom';ReactDOM.render(<h1>Hello, world!h1>,document.getElementById('root'));
react-native
React Native使你只使用JavaScript也能編寫原生移動(dòng)應(yīng)用。它在設(shè)計(jì)原理上和React一致,通過聲明式的組件機(jī)制來搭建豐富多彩的用戶界面。
import React, { Component } from 'react';import { Text, View } from 'react-native';class WhyReactNativeIsSoGreat extends Component {render() {return (<View><Text>如果你喜歡在Web上使用React,那你也肯定會(huì)喜歡React Native.Text><Text>基本上就是用原生組件比如'View'和'Text'來代替web組件'div'和'span'。Text>View>);}}
React Native Renderer 將 React 組件渲染為 Native 視圖。此渲染器在 React Native 內(nèi)部使用。
React Native 產(chǎn)出的并不是“網(wǎng)頁應(yīng)用”, 或者說“HTML5應(yīng)用”,又或者“混合應(yīng)用”。最終產(chǎn)品是一個(gè)真正的移動(dòng)應(yīng)用,從使用感受上和用 Objective-C 或 Java 編寫的應(yīng)用相比幾乎是無法區(qū)分的。React Native 所使用的基礎(chǔ)UI組件和原生應(yīng)用完全一致。你要做的就是把這些基礎(chǔ)組件使用JavaScript 和 React 的方式組合起來。
react-test-renderer
React Test Renderer 將 React 組件渲染為 JSON 樹。這用于 Jest 的快照測試特性。在 npm 上作為 react-test-renderer 包發(fā)布。
import TestRenderer from 'react-test-renderer';function Link(props) {return <a href={props.page}>{props.children}a>;}const testRenderer = TestRenderer.create(<Link page="https://www.facebook.com/">FacebookLink>);console.log(testRenderer.toJSON());// { type: 'a',// props: { href: 'https://www.facebook.com/' },// children: [ 'Facebook' ] }
本質(zhì)上,該包可以在無需使用瀏覽器或 jsdom 的情況下,輕松地抓取由 React DOM 或 React Native渲染出的平臺(tái)視圖層次結(jié)構(gòu)(類似于DOM樹)。
reconciler
即便 React DOM 和 React Native 渲染器的區(qū)別很大,但也需要共享一些邏輯。特別是協(xié)調(diào)算法需要盡可能相似,這樣可以讓聲明式渲染,自定義組件,state,生命周期方法和 refs 等特性,保持跨平臺(tái)工作一致。
為了解決這個(gè)問題,不同的渲染器彼此共享一些代碼。我們稱 React 的這一部分為 “reconciler”。當(dāng)處理類似于 setState() 這樣的更新時(shí),reconciler 會(huì)調(diào)用樹中組件上的 render(),然后決定是否進(jìn)行掛載,更新或是卸載操作。
Reconciler 沒有單獨(dú)的包,因?yàn)樗麄儠簳r(shí)沒有公共 API。相反,它們被如 React DOM 和 React Native 的渲染器排除在外。
協(xié)調(diào)就是不同的渲染器彼此共享的一些代碼,包括 diff 算法。當(dāng)組件的 props 或 state 發(fā)生變化時(shí),React 通過將最新返回的元素與原先渲染的元素進(jìn)行比較,來決定是否有必要進(jìn)行一次實(shí)際的 DOM 更新。當(dāng)它們不相等時(shí),React 才會(huì)更新 DOM。這個(gè)過程被稱為“協(xié)調(diào)”。
“stack” reconciler 是 React 15 及更早的解決方案。Fiber 從 React 16 開始變成了默認(rèn)的 reconciler。
