react源碼解析5.jsx&核心api

react源碼解析5.jsx&核心api

視頻課程(高效學習):進入課程

課程目錄:

1.開篇介紹和面試題

2.react的設計理念

3.react源碼架構

4.源碼目錄結構和調試

5.jsx&核心api

6.legacy和concurrent模式入口函數(shù)

7.Fiber架構

8.render階段

9.diff算法

10.commit階段

11.生命周期

12.狀態(tài)更新流程

13.hooks源碼

14.手寫hooks

15.scheduler&Lane

16.concurrent模式

17.context

18事件系統(tǒng)

19.手寫迷你版react

20.總結&第一章的面試題解答

21.demo

virtual Dom是什么

一句話概括就是,用js對象表示dom信息和結構锄禽,更新時重新渲染更新后的對象對應的dom矾湃,這個對象就是React.createElement()的返回結果

virtual Dom是一種編程方式登钥,它以對象的形式保存在內(nèi)存中寝志,它描述了我們dom的必要信息憨降,并且用類似react-dom等模塊與真實dom同步描焰,這一過程也叫協(xié)調(reconciler)瘫证,這種方式可以聲明式的渲染相應的ui狀態(tài),讓我們從dom操作中解放出來狐赡,在react中是以fiber樹的形式存放組件樹的相關信息撞鹉,在更新時可以增量渲染相關dom疟丙,所以fiber也是virtual Dom實現(xiàn)的一部分

為什么要用virtual Dom

大量的dom操作慢,很小的更新都有可能引起頁面的重新排列鸟雏,js對象優(yōu)于在內(nèi)存中享郊,處理起來更快,可以通過diff算法比較新老virtual Dom的差異孝鹊,并且批量炊琉、異步、最小化的執(zhí)行dom的變更又活,以提高性能

另外就是可以跨平臺苔咪,jsx --> ReactElement對象 --> 真實節(jié)點,有中間層的存在柳骄,就可以在操作真實節(jié)點之前進行對應的處理团赏,處理的結果反映到真實節(jié)點上,這個真實節(jié)點可以是瀏覽器環(huán)境耐薯,也可以是Native環(huán)境

virtual Dom真的快嗎舔清?其實virtual Dom只是在更新的時候快,在應用初始的時候不一定快

react源碼5.1
const div = document.createElement('div');
let str = ''
for(let k in div){
  str+=','+k
}
console.log(str)
react源碼5.2

jsx&createElement

jsx可以聲明式的描述視圖曲初,提升開發(fā)效率体谒,通過babel可以轉換成React.createElement()的語法糖,也是js語法的擴展臼婆。

jsx是ClassComponent的render函數(shù)或者FunctionComponent的返回值抒痒,可以用來表示組件的內(nèi)容,在經(jīng)過babel編譯之后颁褂,最后會被編譯成React.createElement故响,這就是為什么jsx文件要聲明import React from 'react'的原因(react17之后不用導入),你可以在 <a name="https://www.babeljs.cn/repl">babel編譯jsx</a> 站點查看jsx被編譯后的結果

`React.createElement`的源碼中做了如下幾件事
  • 處理config痢虹,把除了保留屬性外的其他config賦值給props
  • 把children處理后賦值給props.children
  • 處理defaultProps
  • 調用ReactElement返回一個jsx對象(virtual-dom)
//ReactElement.js
export function createElement(type, config, children) {
  let propName;

  const props = {};

  let key = null;
  let ref = null;
  let self = null;
  let source = null;

  if (config != null) {
    //處理config被去,把除了保留屬性外的其他config賦值給props
    //...
  }

  const childrenLength = arguments.length - 2;
  //把children處理后賦值給props.children
  //...

  //處理defaultProps
  //...

  return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props,
  );
}

const ReactElement = function(type, key, ref, self, source, owner, props) {
  const element = {
    $$typeof: REACT_ELEMENT_TYPE,//表示是ReactElement類型

    type: type,//class或function
    key: key,//key
    ref: ref,//ref屬性
    props: props,//props
    _owner: owner,
  };

  return element;
};


typeof表示的是組件的類型,例如在源碼中有一個檢查是否是合法Element的函數(shù)奖唯,就是根object.typeof === REACT_ELEMENT_TYPE來判斷的

//ReactElement.js
export function isValidElement(object) {
  return (
    typeof object === 'object' &&
    object !== null &&
    object.$$typeof === REACT_ELEMENT_TYPE
  );
}

如果組件是ClassComponent則type是class本身,如果組件是FunctionComponent創(chuàng)建的糜值,則type是這個function丰捷,源碼中用ClassComponent.prototype.isReactComponent來區(qū)別二者。注意class或者function創(chuàng)建的組件一定要首字母大寫寂汇,不然后被當成普通節(jié)點病往,type就是字符串。

jsx對象上沒有優(yōu)先級骄瓣、狀態(tài)停巷、effectTag等標記,這些標記在Fiber對象上,在mount時Fiber根據(jù)jsx對象來構建畔勤,在update時根據(jù)最新狀態(tài)的jsx和current Fiber對比蕾各,形成新的workInProgress Fiber,最后workInProgress Fiber切換成current Fiber庆揪。

render

//ReactDOMLegacy.js
export function render(
  element: React$Element<any>,//jsx對象
  container: Container,//掛載dom
  callback: ?Function,//回調
) {
  
  return legacyRenderSubtreeIntoContainer(
    null,
    element,
    container,
    false,
    callback,
  );
}

可以看到render所做的事也就是調用legacyRenderSubtreeIntoContainer式曲,這個函數(shù)在下一章講解,這里重點關注ReactDom.render()使用時候的三個參數(shù)缸榛。

component

//ReactBaseClasses.js
function Component(props, context, updater) {
  this.props = props;//props屬性
  this.context = context;//當前的context
  this.refs = emptyObject;//ref掛載的對象
  this.updater = updater || ReactNoopUpdateQueue;//更新的對像
}

Component.prototype.isReactComponent = {};//表示是classComponent

component函數(shù)中主要在當前實例上掛載了props吝羞、context、refs内颗、updater等钧排,所以在組件的實例上能拿到這些,而更新主要的承載結構就是updater均澳, 主要關注isReactComponent恨溜,它用來表示這個組件是類組件

總結:jsx是React.createElement的語法糖,jsx通過babel轉化成React.createElement函數(shù)负懦,React.createElement執(zhí)行之后返回jsx對象筒捺,也叫virtual-dom,F(xiàn)iber會根據(jù)jsx對象和current Fiber進行對比形成workInProgress Fiber

pureComponent也很簡單纸厉,和component差不多系吭,他會進行原型繼承,然后賦值isPureReactComponent

function PureComponent(props, context, updater) {
  this.props = props;
  this.context = context;
  this.refs = emptyObject;
  this.updater = updater || ReactNoopUpdateQueue;
}

const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
pureComponentPrototype.constructor = PureComponent;
Object.assign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;

export {Component, PureComponent};
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末颗品,一起剝皮案震驚了整個濱河市肯尺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌躯枢,老刑警劉巖则吟,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異锄蹂,居然都是意外死亡氓仲,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門得糜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來敬扛,“玉大人,你說我怎么就攤上這事朝抖∩都” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵治宣,是天一觀的道長急侥。 經(jīng)常有香客問我砌滞,道長,這世上最難降的妖魔是什么坏怪? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任贝润,我火速辦了婚禮,結果婚禮上陕悬,老公的妹妹穿的比我還像新娘题暖。我一直安慰自己,他們只是感情好捉超,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布胧卤。 她就那樣靜靜地躺著,像睡著了一般拼岳。 火紅的嫁衣襯著肌膚如雪枝誊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天惜纸,我揣著相機與錄音叶撒,去河邊找鬼。 笑死耐版,一個胖子當著我的面吹牛祠够,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播粪牲,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼古瓤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了腺阳?” 一聲冷哼從身側響起落君,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎亭引,沒想到半個月后绎速,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡焙蚓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年纹冤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片购公。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡赵哲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出君丁,到底是詐尸還是另有隱情,我是刑警寧澤将宪,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布绘闷,位于F島的核電站橡庞,受9級特大地震影響,放射性物質發(fā)生泄漏印蔗。R本人自食惡果不足惜扒最,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望华嘹。 院中可真熱鬧吧趣,春花似錦、人聲如沸耙厚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽薛躬。三九已至俯渤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間型宝,已是汗流浹背八匠。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留趴酣,地道東北人梨树。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像岖寞,于是被迫代替她去往敵國和親抡四。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容