<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一名中/高級前端工程師的自檢清單-React 篇

          共 7243字,需瀏覽 15分鐘

           ·

          2021-12-10 23:28

          歡迎關(guān)注前端早茶,與廣東靚仔攜手共同進階~

          一、前言

          ? ? 你真的了解 React 嗎?我們在面試中往往涉及 React 時,第一個問題就是“解釋 React 是什么”。解釋一種技術(shù)是什么,在面試中也是非常常見的引起 話題的題目。本篇文章我就帶你掌握這一類概念題的解答技巧。

          二、正文

          一. 說說對 React 的理解,有哪些特性

          官方的解釋:React 是一個 UI 庫,它的核心思想是UI=F(data), 即界面的呈現(xiàn)是由函數(shù)傳入的參數(shù)決定的

          開發(fā)者不再需要關(guān)心界面如何渲染的,只要關(guān)心數(shù)據(jù)的生成和傳遞,這大大提高的開發(fā)者的開發(fā)效率,節(jié)省了開發(fā)時間

          其次 React 設(shè)計的

          • 使用類似 HTML 的JSX語法來描述視圖
          • 通過虛擬DOM修改真實DOM
          • 通過setState修改數(shù)據(jù)
          • 在不同的生命周期階段做不同的事
          • 源碼底層對真實 DOM 事件進行封裝,使用事件委托的方式來捕獲 DOM 事件
          • ....

          等特性進一步簡化的 真實 DOM 操作的復(fù)雜性

          二. 說說真實 DOM 與虛擬 DOM 的區(qū)別,優(yōu)缺點

          f64dc5ce282cf3125c648929df638044.webp虛擬DOM

          2.1 虛擬 DOM 是什么

          • 真實DOM就是我們在瀏覽器開發(fā)者工具中看到的DOM結(jié)構(gòu)
          • 虛擬DOM簡單來說就是 JS 對象,此對象中的字段包含了對真實DOM的描述:
            • type:是什么標(biāo)簽/元素
            • props:標(biāo)簽/元素有哪些屬性
            • children:是否有子元素
          9c9f5e365f7bcccb3edd0676eaa0da28.webpa

          2.2 虛擬 DOM 大概是如何工作的

          當(dāng)?DOM?操作(渲染更新)比較頻繁時,

          React 底層會先將前后兩次的虛擬DOM?樹進行對比,

          定位出具體需要更新的部分,生成一個補丁集

          最后只把“補丁”打在需要更新的那部分真實DOM?上,實現(xiàn)精準(zhǔn)的“差量更新”。

          2.3 虛擬 DOM 的優(yōu)點

          1. 解決了頻繁操作真實 DOM 的低效率工作-不直接操作 DOM,數(shù)據(jù)驅(qū)動視圖,也在一定程度上提升了性能
          2. 解決了擴平臺開發(fā)的問題,因為虛擬 DOM 描述的東西可以是真實 DOM,也可以是安卓界面。IOS 界面等等,這就可以對接不同平臺的渲染邏輯。從而實現(xiàn)"一次編碼,多端運行"(如 React,React Native)

          2.4 虛擬 DOM 的缺點

          如果當(dāng)虛擬 DOM 的構(gòu)建和diff的過程相對復(fù)雜(比如很多遞歸遍歷等操作),那么虛擬 DOM 的 JS 計算是比較耗時的

          三. 說說 Diff 算法

          122663189db3902559b71ffaa8d25276.webpDiff算法

          一般的原始 diff 思路算法復(fù)雜度是O(n^3),即循環(huán)遞歸進行樹節(jié)點的一一對比

          但 React 的?diff 算法是?O (n)?復(fù)雜度的思路

          當(dāng)對比兩棵虛擬 DOM 樹時,React 首先比較兩棵樹的根節(jié)點。不同類型的根節(jié)點元素會有不同的形態(tài)

          當(dāng)對比兩個相同類型的 React 元素時,React 會保留 DOM 節(jié)點,僅比對及更新有改變的屬性。

          1. 當(dāng)根節(jié)點為不同類型的元素時,React 會拆卸原有的樹并且建立起新的樹,這大大減少了?Diff?過程中冗余的遞歸操作
          2. 當(dāng)對比兩個相同類型的 React 元素時,React 會保留 DOM 節(jié)點,僅比對及更新有改變的屬性
          3. 列表形式的子元素比較:React 引入了?key 屬性。當(dāng)子元素?fù)碛?key?時,React 使用?key?來匹配原有樹上的子元素以及最新樹上的子元素,如果?key不同 不同則會拆卸原有的?key?節(jié)點并且建立起新的?key?節(jié)點

          詳細(xì)內(nèi)容請參考React 官方文檔- Diffing 算法[2]

          四. 說說 React 聲明周期有哪些不同階段,每個階段對應(yīng)的方法是什么

          2df0d558ab30cff16debadeed21d6576.webpimage.png

          4.1 創(chuàng)建階段

          1. constructor():組件的構(gòu)造函數(shù),組件更新到界面上之前會先調(diào)用

          • 用于初始化內(nèi)部狀態(tài),很少使用
          • 唯一可以直接修改?state?的地方

          static getDerivedStateFromProps(nextProps, prevState):用于從外部的屬性去初始化一些內(nèi)部的狀態(tài)

          • 當(dāng)?state?需要從?props?初始化時使用
          • 盡量不要使用,維護?state/props?狀態(tài)一致性會增加復(fù)雜度
          • 每次?render?都會調(diào)用
          • 典型場景: 表單控件獲取默認(rèn)值

          render()::組件必須定義的一個生命周期方法,用來描述 虛擬 DOM 結(jié)構(gòu)

          componentDidMount(): 用于數(shù)據(jù)請求,定義一些外部資源等等副作用

          • UI 渲染完成后調(diào)用
          • 只執(zhí)行一次
          • 典型場景:獲取外部資源

          4.2 更新階段

          1. static getDerivedStateFromProps(nextProps, prevState)
          2. shouldComponentUpdate(nextProps, nextState):告訴組件是否需要重新渲染,用于性能優(yōu)化,比如判定指定 props 發(fā)生改變,組件才進行重新渲染
          • 決定虛擬 DOM 是否需要重繪
          • 一般可以由?PureComponent?自動實現(xiàn)
          • 典型場景:性能優(yōu)化
          render()getSnapshotBeforeUpdate(prevProps, prevState)
          • 在最近一次渲染輸出(提交到 DOM 節(jié)點)之前調(diào)用,state 已更新
          • 與?componentDidUpdate?搭配使用
          • 典型場景:捕獲?render?之前的 DOM 狀態(tài)
          componentDidUpdate(prevProps, prevState)
          • 每次 UI 更新時被調(diào)用
          • 典型場景:頁面需要根據(jù)?props?變化重新獲取數(shù)據(jù)

          4.3 卸載階段

          1. componentWillUnmount(): 做些資源釋放,卸載副作用的事情
          • 此方法中可以執(zhí)行必要的清理操作,例如,清除 timer,取消網(wǎng)絡(luò)請求或清除在

          詳細(xì)內(nèi)容請參考React 知識體系之生命周期及使用場景[3]

          五. 說說對 State 和 Props 的理解,有什么區(qū)別

          • state用于組件內(nèi)部數(shù)據(jù)傳遞,state?數(shù)據(jù)可以通過this.setSate或者useState進行修改

          • props用于組件外部組件數(shù)據(jù)傳遞,props不能直接修改.主要使用場景是:

            • 兄弟組件通信
            • 父子組件通信
            • "爺孫組件"組件通信
          • props的使用范圍雖然更加廣泛,但也有其局限性:對于嵌套層次較深的組件,如果使用props傳遞數(shù)據(jù),會導(dǎo)致代碼冗余,增加數(shù)據(jù)傳遞的復(fù)雜度

          六. super 和 super(props)有什么區(qū)別

          在 JavaScript 中,super 指的是父類構(gòu)造函數(shù)。(在我們的示例中,它指向 React.Component 實現(xiàn)。)

          在調(diào)用父類的構(gòu)造函數(shù)之前,你是不能在?constructor?中使用?this?關(guān)鍵字的。JavaScript 不允許這個行為

          class?Checkbox?extends?React.Component?{
          ??constructor(props)?{
          ????//?????還不能使用?`this`
          ????super(props);
          ????//????現(xiàn)在可以了
          ????this.state?=?{?isOn:?true?};
          ??}
          ??//?...
          }
          復(fù)制代碼

          為什么一定要傳遞?props?呢?為了讓?React.Component?構(gòu)造函數(shù)能夠初始化?this.props

          React 內(nèi)部代碼:

          //?React?內(nèi)部
          class?Component?{
          ??constructor(props)?{
          ????this.props?=?props;
          ????//?...
          ??}
          }
          復(fù)制代碼

          實例代碼:

          class?Button?extends?React.Component?{
          ??constructor(props)?{
          ????super();?//???We?forgot?to?pass?props
          ????console.log(props);?//???{}
          ????console.log(this.props);?//???undefined
          ??}
          ??//?...
          }
          復(fù)制代碼
          class?Button?extends?React.Component?{
          ??constructor(props)?{
          ????super(props);?//???We?passed?props
          ????console.log(props);?//???{}
          ????console.log(this.props);?//???{}
          ??}
          ??//?...
          }
          復(fù)制代碼

          有了 Hooks 以后,我們幾乎就不需要?super?和?this?了

          詳細(xì)內(nèi)容請參考為什么我們要寫 super(props) ?[4]

          七. 說說 React 中的 setState 機制

          033f733bea892de5a3eff53bf465e8a6.webpsetState

          7.1 合成事件、鉤子函數(shù)中的 setState

          • 在鉤子函數(shù)中?setSate?拿不到最新值
          • 在合成事件中執(zhí)行多個同樣的?setSate,最終只會執(zhí)行一次,并且也拿不到最新值

          原因:

          1. 一次?setState?就會觸發(fā)一次?re-render(重渲染)
          2. 為了避免頻繁的?re-ernder,setState?被設(shè)計成異步的形式
          3. 每來一個?setState,就把它塞進一個隊列里“攢起來”。等時機成熟,再把“攢起來”的?state?結(jié)果做合并(對于相同屬性的設(shè)置,React 只會為其保留最后一次的更新),最后只針對最新的?state?值走一次更新流程。這個過程,叫做**批量更新**

          7.2?setTimeout/setInterval、原生 DOM中的 setState

          • 在?setTimeout/setInterval?中設(shè)置?setState,可以拿到最新的值
          • 原生 DOM?事件中設(shè)置?setState,可以拿到最新的值

          原因:

          setState?的“異步”并不是說內(nèi)部由異步代碼實現(xiàn),其實源碼本身執(zhí)行的過程和代碼都是同步的,

          只是合成事件和鉤子函數(shù)的調(diào)用順序在更新之前,導(dǎo)致在合成事件和鉤子函數(shù)中沒法立馬拿到更新后的值,形了所謂的“異步”

          setState?的批量更新優(yōu)化也是建立在“異步”(合成事件、鉤子函數(shù))之上的,在原生事件和?setTimeout?中不會批量更新

          詳細(xì)內(nèi)容請參考setState 到底是同步的,還是異步的?[5]

          八. 說說對 React 事件機制的理解

          af8921f7c51c18be65c6501991cd38d5.webpReact事件機制

          8.1 React 中的事件是什么

          React 中的事件叫合成事件:React 底層使用事件委托的方式對真實 DOM 事件進行了封裝,使合成事件具有更好的瀏覽器兼容性和性能

          8.2 合成事件的大致原理

          當(dāng)事件在具體的 DOM 節(jié)點上被觸發(fā)后,最終都會冒泡到 document 上,document 上所綁定的統(tǒng)一事件處理程序會將事件分發(fā)到具體的組件實例

          8.3 React 為什么要重新設(shè)計出一個合成事件

          合成事件是 React 自定義的事件對象,它符合 W3C 規(guī)范,在底層抹平了不同瀏覽器的差異,在上層面向開發(fā)者暴露統(tǒng)一的、穩(wěn)定的、與 DOM 原生事件相同的事件接口。

          開發(fā)者們由此便不必再關(guān)注煩瑣的兼容性問題,可以專注于業(yè)務(wù)邏輯的開發(fā)。

          • 雖然合成事件并不是原生 DOM 事件,但它保存了原生 DOM 事件的引用。當(dāng)你需要訪問原生 DOM 事件對象時,可以通過合成事件對象的?e.nativeEvent?屬性獲取到它
          • 合成事件無法獲取到真實 DOM,但可以通過 React 提供refAPI 進行獲取

          詳細(xì)內(nèi)容請參考React 事件與 DOM 事件有何不同?[6]

          九. React 事件綁定的方式有哪些

          9.1 類組件

          9.1.1 render 方法中使用 bind

          這種方式在組件每次 render 渲染的時候,都會重新進行 bind 的操作,影響性能

          class?App?extends?React.Component?{
          ??handleClick()?{
          ????console.log("this?>?",?this);
          ??}
          ??render()?{
          ????return?<div?onClick={this.handleClick.bind(this)}>testdiv>;
          ??}
          }
          復(fù)制代碼

          9.1.2 render 方法中使用箭頭函數(shù)

          通過 ES6 的上下文來將 this 的指向綁定給當(dāng)前組件,同樣在每一次 render 的時候都會生成新的方法,影響性能

          class?App?extends?React.Component?{
          ??handleClick()?{
          ????console.log("this?>?",?this);
          ??}
          ??render()?{
          ????return?<div?onClick={(e)?=>?this.handleClick(e)}>testdiv>;
          ??}
          }
          復(fù)制代碼

          9.1.3 constructor 中 bind

          在 constructor 中預(yù)先 bind 當(dāng)前組件,可以避免在 render 操作中重復(fù)綁定

          class?App?extends?React.Component?{
          ??constructor(props)?{
          ????super(props);
          ????this.handleClick?=?this.handleClick.bind(this);
          ??}
          ??handleClick()?{
          ????console.log("this?>?",?this);
          ??}
          ??render()?{
          ????return?<div?onClick={this.handleClick}>testdiv>;
          ??}
          }
          復(fù)制代碼

          9.1.4 定義階段使用箭頭函數(shù)綁定

          能夠避免在 render 操作中重復(fù)綁定

          class?App?extends?React.Component?{
          ??constructor(props)?{
          ????super(props);
          ??}
          ??handleClick?=?()?=>?{
          ????console.log("this?>?",?this);
          ??};
          ??render()?{
          ????return?<div?onClick={this.handleClick}>testdiv>;
          ??}
          }
          復(fù)制代碼

          9.2 函數(shù)式組件

          • 箭頭函數(shù)

          函數(shù)組件沒有實例,因此沒有this

          const?App?=?()?=>?{
          ??handleClick?=?(e)?=>?{
          ????console.log(e);
          ??};
          ??return?<div?onClick={this.handleClick}>testdiv>;
          };
          復(fù)制代碼

          詳細(xì)內(nèi)容請參考React 構(gòu)建組件的方式有哪些[7]

          十. React 構(gòu)建組件的方式有哪些

          1. 類組件
          2. 高階組件
          3. render props
          4. 純函數(shù)組件
          5. Hooks組件
          6. 自定義Hooks

          詳細(xì)內(nèi)容請參考React 構(gòu)建組件的方式有哪些[8]

          十一. React 中組件通信的方式有哪些

          • 單個組件內(nèi)部數(shù)據(jù)傳遞
            • state
          • 父組件向子組件傳遞
            • props
          • 子組件向父組件傳遞
            • props
          • 兄弟組件之間的通信
            • props
          • 父組件向后代組件傳遞
            • props
            • Context API
            • Redux
            • 發(fā)布-訂閱模式
            • EventBus
          • 非關(guān)系組件傳遞
            • Context API
            • Redux
            • 發(fā)布-訂閱模式
            • EventBus

          十二. React 的 key 有什么作用

          說到 React 的 key,就要說到 React 的 Diff 算法

          詳細(xì)內(nèi)容請參考React 列表循環(huán)為什么需要 key[9]

          三、最后

          關(guān)注我,一起攜手進階

          歡迎關(guān)注前端早茶,與廣東靚仔攜手共同進階~


          b68c258459b9bc472362c7108f96212d.webp點個在看支持我吧d9c942755669b75e8fbb5a29b343959c.webp

          參考資料

          [1]

          https://juejin.cn/post/6978685539985653767:?https://juejin.cn/post/6978685539985653767

          [2]

          https://zh-hans.reactjs.org/docs/reconciliation.html#the-diffing-algorithm:?https://link.juejin.cn?target=https%3A%2F%2Fzh-hans.reactjs.org%2Fdocs%2Freconciliation.html%23the-diffing-algorithm

          [3]

          https://juejin.cn/post/6981739846461030408:?https://juejin.cn/post/6981739846461030408

          [4]

          https://overreacted.io/zh-hans/why-do-we-write-super-props/:?https://link.juejin.cn?target=https%3A%2F%2Foverreacted.io%2Fzh-hans%2Fwhy-do-we-write-super-props%2F

          [5]

          https://www.yuque.com/u221766/xgl0mb/oxl3ik:?https://link.juejin.cn?target=https%3A%2F%2Fwww.yuque.com%2Fu221766%2Fxgl0mb%2Foxl3ik

          [6]

          https://www.yuque.com/u221766/xgl0mb/iu68y0:?https://link.juejin.cn?target=https%3A%2F%2Fwww.yuque.com%2Fu221766%2Fxgl0mb%2Fiu68y0

          [7]

          https://juejin.cn/post/6952907248393781284#heading-2:?https://juejin.cn/post/6952907248393781284#heading-2

          [8]

          https://juejin.cn/post/6952907248393781284:?https://juejin.cn/post/6952907248393781284

          [9]

          https://juejin.cn/post/6940974776441634823:?https://juejin.cn/post/6940974776441634823


          來源:望道同學(xué)

          https://juejin.cn/post/6981831831112908831

          聲明:文章著作權(quán)歸作者所有,如有侵權(quán),請聯(lián)系小編刪除。
          瀏覽 58
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  韩国三级HD中文久久精品车子 | 毛片内射 | 亚洲性爱电影在线 | 日本视频一区二区三区四区 | 国产乱婬AAAA片视频 |