react源碼解析20.總結(jié)&第一章的面試題解答

react源碼解析20.總結(jié)&第一章的面試題解答

視頻課程(高效學(xué)習(xí)):進入課程

課程目錄:

1.開篇介紹和面試題

2.react的設(shè)計理念

3.react源碼架構(gòu)

4.源碼目錄結(jié)構(gòu)和調(diào)試

5.jsx&核心api

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

7.Fiber架構(gòu)

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.總結(jié)&第一章的面試題解答

21.demo

總結(jié)

至此我們介紹了react的理念邑蒋,如果解決cpu和io的瓶頸剃氧,關(guān)鍵是實現(xiàn)異步可中斷的更新

我們介紹了react源碼架構(gòu)(ui=fn(state))耍目,從scheduler開始調(diào)度(根據(jù)過期事件判斷優(yōu)先級)房交,經(jīng)過render階段的深度優(yōu)先遍歷形成effectList(中間會執(zhí)行reconcile|diff),交給commit處理真實節(jié)點(中間穿插生命周期和部分hooks)糙捺,而這些調(diào)度的過程都離不開Fiber的支撐惑芭,F(xiàn)iber是工作單元,也是節(jié)點優(yōu)先級继找、更新UpdateQueue、節(jié)點信息的載體逃沿,F(xiàn)iber雙緩存則提供了對比前后節(jié)點更新的基礎(chǔ)婴渡。我們還介紹了jsx是React.createElement的語法糖。Lane模型則提供了更細粒度的優(yōu)先級對比和計算凯亮,這一切都為concurrent mode提供了基礎(chǔ)边臼,在這之上變可以實現(xiàn)Suspense和batchedUpdate(16、17版本實現(xiàn)的邏輯不一樣)假消,18章context的valueStack和valueCursor在整個架構(gòu)中運行機制柠并,19章介紹了新版事件系統(tǒng),包括事件生產(chǎn)富拗、監(jiān)聽和觸發(fā)

面試題簡答(詳見視頻源碼角度講解)

  1. jsx和Fiber有什么關(guān)系

    答:mount時通過jsx對象(調(diào)用createElement的結(jié)果)調(diào)用createFiberFromElement生成Fiber
    update時通過reconcileChildFibers或reconcileChildrenArray對比新jsx和老的Fiber(current Fiber)生成新的wip Fiber樹

  2. react17之前jsx文件為什么要聲明import React from 'react'臼予,之后為什么不需要了

    答:jsx經(jīng)過編譯之后編程React.createElement,不引入React就會報錯啃沪,react17改變了編譯方式粘拾,變成了jsx.createElement

    function App() {
      return <h1>Hello World</h1>;
    }
    //轉(zhuǎn)換后
    import {jsx as _jsx} from 'react/jsx-runtime';
    
    function App() {
      return _jsx('h1', { children: 'Hello world' });
    }
    
  1. Fiber是什么,它為什么能提高性能

    答:Fiber是一個js對象创千,能承載節(jié)點信息缰雇、優(yōu)先級、updateQueue追驴,同時它還是一個工作單元械哟。

    1. Fiber雙緩存可以在構(gòu)建好wip Fiber樹之后切換成current Fiber,內(nèi)存中直接一次性切換殿雪,提高了性能
    2. Fiber的存在使異步可中斷的更新成為了可能暇咆,作為工作單元,可以在時間片內(nèi)執(zhí)行工作,沒時間了交還執(zhí)行權(quán)給瀏覽器糯崎,下次時間片繼續(xù)執(zhí)行之前暫停之后返回的Fiber
    3. Fiber可以在reconcile的時候進行相應(yīng)的diff更新几缭,讓最后的更新應(yīng)用在真實節(jié)點上

hooks

  1. 為什么hooks不能寫在條件判斷中

    答:hook會按順序存儲在鏈表中,如果寫在條件判斷中沃呢,就沒法保持鏈表的順序

狀態(tài)/生命周期

  1. setState是同步的還是異步的

    答:legacy模式下:命中batchedUpdates時是異步 未命中batchedUpdates時是同步的

    concurrent模式下:都是異步的

  2. componentWillMount年栓、componentWillMount、componentWillUpdate為什么標記UNSAFE

    答:新的Fiber架構(gòu)能在scheduler的調(diào)度下實現(xiàn)暫停繼續(xù)薄霜,排列優(yōu)先級某抓,Lane模型能使Fiber節(jié)點具有優(yōu)先級,在高優(yōu)先級的任務(wù)打斷低優(yōu)先級的任務(wù)時惰瓜,低優(yōu)先級的更新可能會被跳過否副,所有以上生命周期可能會被執(zhí)行多次,和之前版本的行為不一致崎坊。

組件

  1. react元素$$typeof屬性什么

    答:用來表示元素的類型备禀,是一個symbol類型

  2. react怎么區(qū)分Class組件和Function組件

    答:Class組件prototype上有isReactComponent屬性

  3. 函數(shù)組件和類組件的相同點和不同點

    答:相同點:都可以接收props返回react元素

    不同點:

    編程思想:類組件需要創(chuàng)建實例,面向?qū)ο竽巫幔瘮?shù)組件不需要創(chuàng)建實例曲尸,接收輸入,返回輸出男翰,函數(shù)式編程

    內(nèi)存占用:類組建需要創(chuàng)建并保存實例另患,占用一定的內(nèi)存

    值捕獲特性:函數(shù)組件具有值捕獲的特性 下面的函數(shù)組件換成類組件打印的num一樣嗎

    export default function App() {
      const [num, setNum] = useState(0);
      const click = () => {
        setTimeout(() => {
          console.log(num);
        }, 3000);
        setNum(num + 1);
      };
    
      return <div onClick={click}>click {num}</div>;
    }
    
    
    export default class App extends React.Component {
      state = {
        num: 0
      };
    
      click = () => {
        setTimeout(() => {
          console.log(this.state.num);
        }, 3000);
        this.setState({ num: this.state.num + 1 });
      };
    
      render() {
        return <div onClick={this.click}>click {this.state.num}</div>;
      }
    }
    
    
    

可測試性:函數(shù)組件方便測試

狀態(tài):類組件有自己的狀態(tài),函數(shù)組件沒有只能通過useState

生命周期:類組件有完整生命周期蛾绎,函數(shù)組件沒有可以使用useEffect實現(xiàn)類似的生命周期

邏輯復(fù)用:類組件繼承 Hoc(邏輯混亂 嵌套)昆箕,組合優(yōu)于繼承,函數(shù)組件hook邏輯復(fù)用

跳過更新:shouldComponentUpdate PureComponent租冠,React.memo

發(fā)展未來:函數(shù)組件將成為主流鹏倘,屏蔽this、規(guī)范顽爹、復(fù)用第股,適合時間分片和渲染

開放性問題

  1. 說說你對react的理解/請說一下react的渲染過程

    答:是什么:react是構(gòu)建用戶界面的js庫

    能干什么:可以用組件化的方式構(gòu)建快速響應(yīng)的web應(yīng)用程序

    如何干:聲明式(jsx) 組件化(方便拆分和復(fù)用 高內(nèi)聚 低耦合) 一次學(xué)習(xí)隨處編寫

    做的怎么樣: 優(yōu)缺(社區(qū)繁榮 一次學(xué)習(xí)隨處編寫 api簡介)缺點(沒有系統(tǒng)解決方案 選型成本高 過于靈活)

    設(shè)計理念:跨平臺(虛擬dom) 快速響應(yīng)(異步可中斷 增量更新)

    性能瓶頸:cpu io fiber時間片 concurrent mode

    渲染過程:scheduler render commit Fiber架構(gòu)

  2. 聊聊react生命周期
    詳見第11章

  3. 簡述diff算法
    詳見第9章

  4. react有哪些優(yōu)化手段

    答:shouldComponentUpdate、不可變數(shù)據(jù)結(jié)構(gòu)话原、列表key夕吻、pureComponent、react.memo繁仁、useEffect依賴項涉馅、useCallback、useMemo黄虱、bailoutOnAlreadyFinishedWork ...

  5. react為什么引入jsx

    答:jsx聲明式 虛擬dom跨平臺

    解釋概念:jsx是js語法的擴展 可以很好的描述ui jsx是React.createElement的語法糖

    想實現(xiàn)什么目的:聲明式 代碼結(jié)構(gòu)簡潔 可讀性強 結(jié)構(gòu)樣式和事件可以實現(xiàn)高內(nèi)聚 低耦合 稚矿、復(fù)用和組合 不需要引入新的概念和語法 只寫js, 虛擬dom跨平

    有哪些可選方案:模版語法 vue ag引入了控制器 作用域 服務(wù)等概念

    jsx原理:babel抽象語法樹 classic是老的轉(zhuǎn)換 automatic新的轉(zhuǎn)換

  6. 說說virtual Dom的理解

    答:是什么:React.createElement函數(shù)返回的就是虛擬dom,用js對象描述真實dom的js對象

    優(yōu)點:處理了瀏覽器的兼容性 防范xss攻擊 跨平臺 差異化更新 減少更新的dom操作

    缺點:額外的內(nèi)存 初次渲染不一定快

  7. 你對合成事件的理解

    類型 原生事件 合成事件
    命名方式 全小寫 小駝峰
    事件處理函數(shù) 字符串 函數(shù)對象
    阻止默認行為 返回false event.preventDefault()

    理解:

    • React把事件委托到document上(v17是container節(jié)點上)
    • 先處理原生事件 冒泡到document上在處理react事件
    • React事件綁定發(fā)生在reconcile階段 會在原生事件綁定前執(zhí)行

    優(yōu)勢:

    • 進行了瀏覽器兼容晤揣。頂層事件代理桥爽,能保證冒泡一致性(混合使用會出現(xiàn)混亂)
    • 默認批量更新
    • 避免事件對象頻繁創(chuàng)建和回收,react引入事件池昧识,在事件池中獲取和釋放對象(react17中廢棄)
      react17事件綁定在容器上了
  1. 我們寫的事件是綁定在dom上么钠四,如果不是綁定在哪里?
    答:v16綁定在document上跪楞,v17綁定在container上
  2. 為什么我們的事件手動綁定this(不是箭頭函數(shù)的情況)
    答:合成事件監(jiān)聽函數(shù)在執(zhí)行的時候會丟失上下文
  3. 為什么不能用 return false來阻止事件的默認行為缀去?
    答:說到底還是合成事件和原生事件觸發(fā)時機不一樣
  4. react怎么通過dom元素,找到與之對應(yīng)的 fiber對象的甸祭?
    答:通過internalInstanceKey對應(yīng)
    react源碼18.2

解釋結(jié)果和現(xiàn)象

  1. 點擊Father組件的div缕碎,Child會打印Child嗎

    function Child() {
      console.log('Child');
      return <div>Child</div>;
    }
    
    
    function Father(props) {
      const [num, setNum] = React.useState(0);
      return (
        <div onClick={() => {setNum(num + 1)}}>
          {num}
          {props.children}
        </div>
      );
    }
    
    
    function App() {
      return (
        <Father>
          <Child/>
        </Father>
      );
    }
    
    const rootEl = document.querySelector("#root");
    ReactDOM.render(<App/>, rootEl);
    
答: 不會,源碼中是否命中bailoutOnAlreadyFinishedWork
  1. 打印順序是什么

    function Child() {
      useEffect(() => {
        console.log('Child');
      }, [])
      return <h1>child</h1>;
    }
    
    function Father() {
      useEffect(() => {
        console.log('Father');
      }, [])
      
      return <Child/>;
    }
    
    function App() {
      useEffect(() => {
        console.log('App');
      }, [])
    
      return <Father/>;
    }
    
答:Child 池户,F(xiàn)ather 咏雌,App ,render階段mount時深度優(yōu)先遍歷校焦,commit階段useEffect執(zhí)行時機
  1. useLayout/componentDidMount和useEffect的區(qū)別是什么

    class App extends React.Component {
      componentDidMount() {
        console.log('mount');
      }
    }
    
    useEffect(() => {
      console.log('useEffect');
    }, [])
    
答:他們在commit階段不同時機執(zhí)行处嫌,useEffect在commit階段結(jié)尾異步調(diào)用,useLayout/componentDidMount同步調(diào)用

![react源碼20.1](https://upload-images.jianshu.io/upload_images/25882458-4dc6ac1da89812b9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  1. 如何解釋demo_4斟湃、demo_8、demo_9出現(xiàn)的現(xiàn)象

    答:demo_4:useEffect和useLayoutEffect的區(qū)別
    demo_8:任務(wù)的優(yōu)先級有關(guān)檐薯,見源碼分析視頻
    demo_9:批量更新有關(guān)凝赛,見源碼分析視頻

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市坛缕,隨后出現(xiàn)的幾起案子墓猎,更是在濱河造成了極大的恐慌,老刑警劉巖赚楚,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件毙沾,死亡現(xiàn)場離奇詭異,居然都是意外死亡宠页,警方通過查閱死者的電腦和手機左胞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來举户,“玉大人烤宙,你說我怎么就攤上這事〖筻遥” “怎么了躺枕?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我拐云,道長罢猪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任叉瘩,我火速辦了婚禮膳帕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘房揭。我一直安慰自己备闲,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布捅暴。 她就那樣靜靜地躺著恬砂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蓬痒。 梳的紋絲不亂的頭發(fā)上泻骤,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天,我揣著相機與錄音梧奢,去河邊找鬼狱掂。 笑死,一個胖子當(dāng)著我的面吹牛亲轨,可吹牛的內(nèi)容都是我干的趋惨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼惦蚊,長吁一口氣:“原來是場噩夢啊……” “哼器虾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蹦锋,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤兆沙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后莉掂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體葛圃,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年憎妙,在試婚紗的時候發(fā)現(xiàn)自己被綠了库正。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡厘唾,死狀恐怖诀诊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情阅嘶,我是刑警寧澤属瓣,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布载迄,位于F島的核電站,受9級特大地震影響抡蛙,放射性物質(zhì)發(fā)生泄漏护昧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一粗截、第九天 我趴在偏房一處隱蔽的房頂上張望惋耙。 院中可真熱鬧,春花似錦熊昌、人聲如沸绽榛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽灭美。三九已至,卻和暖如春昂利,著一層夾襖步出監(jiān)牢的瞬間届腐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工蜂奸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留犁苏,地道東北人。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓扩所,卻偏偏與公主長得像围详,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子祖屏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

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