一道 React 面試題:在瀏覽器、組件和元素中都渲染了些什麼?

一道 React 面試題:在瀏覽器、組件和元素中都渲染了些什麼?

瘋狂的技術宅 前端先鋒 前端

一道 React 面試題:在瀏覽器、組件和元素中都渲染了些什麼?
這道題的答案有點複雜。react


首先要搞清楚 element 和 component 是否是一回事?
面試

從技術上來講,ReactDOM 不會在 DOM 中渲染 React 組件或 React 元素。它渲染由其組件實例支持的 DOM 元素。對於類組件來講這是正確的。可是對於函數組件,ReactDOM 僅渲染 DOM 元素。函數組件沒有實例(能夠經過 this 訪問),所以在使用函數組件時,ReactDOM 會渲染由函數返回的元素所生成的 DOM 元素。算法

你須要在這裏理解的是,React 元素不一樣於 DOM 元素。React 元素只是 HTML 元素、React 組件或它們的混合的「描述」。數組

好吧,一個更好的面試題可能應該這樣問:當你在JSX中使用 <MyComponent/> 之類的東西時,它是組件、元素仍是實例?瀏覽器

這是一個元素,但不是 DOM 元素,而是一個 React元 素。由於任何 JSX 標籤都會被轉換爲 React.createElement 再去調用。ide

可是要想讓 React 繼續使用這個 React 元素的話,必須調用一個函數或從一個類中建立實例。函數

你可能會在一些 React 教程中看到 組件(component)、元素(element) 和 實例(instance) 這些詞。我在這裏混用這些詞是不對的,可是我認爲 React 的初學者須要瞭解它們的區別。React 官方博客上有一篇文章專門說明這些概念,但我認爲這些內容對於初學者來講還遠遠不夠。this

如下是這些術語的簡單定義:翻譯

  • React Component 是模板,藍圖,全局定義的。能夠是函數或類(帶有渲染功能)。
  • React Element 是從組件中返回的東西。這個對象實際上描述了組件所表明的 DOM 節點。對於函數組件來講,此元素是函數返回的對象。對於類組件,元素是組件的渲染函數返回的對象。React 元素不是咱們在瀏覽器中所看到的。它們只是內存中的對象,咱們沒法對其進行任何更改。
  • React 在其內部經過建立、更新和銷燬 instance 來找出須要渲染給瀏覽器的 DOM 元素樹。使用類組件時,一般將其瀏覽器渲染的 DOM 元素稱爲組件實例。你能夠渲染同一組件的多個實例。實例是你在基於類的組件內部使用的 this 關鍵字。你不須要手動從類建立實例,只須要記住它就在 React 的內存中便可。
  • 基於函數的 React 元素沒有實例。一個函數組件仍然能夠被屢次渲染,可是 React 不會將本地實例與每一個渲染相關聯。它只是用函數的調用來肯定要爲該函數渲染的 DOM 元素。
    最重要的是,ReactDOM 不會在瀏覽器中渲染組件,也不會渲染元素(這裏的術語元素表明 React.createElement 的返回值)。它也不渲染實例。它只渲染 DOM 元素。

不幸的是,使用術語組件既指模板又指經過模板使用的任何一種實例或者調用,這彷佛是很廣泛的。人們對此感到困惑很正常,這挺痛苦的。

每一個 React 應用都從一個使用 React element 的 render 調用開始。下面以 reactjs.org 官網提供的 HelloMessage 案例做爲例子,我對這個例子稍微作了一些修改,使其具備了函數組件:

const Today = () => (
  <div>Today is {new Date().toDateString()}</div>
);class HelloMessage extends React.Component {
  render() {
    return (
      <React.Fragment>
        <div>Hello {this.props.name}</div>
        <Today />
      </React.Fragment>
    );
  }
}ReactDOM.render(
  <HelloMessage name="Taylor" />,
  mountNode
);

第一個 React 元素是咱們在 ReactDOM.render 調用中開始的元素:

<HelloMessage name="Taylor" /> // 這是 React element

這個 React 元素描述了要渲染的 DOM 樹應該以 HelloMessage 組件和值等於 Taylor 的 prop name 開始。

</>如今回答問題:HelloMessage 是什麼?
每當 React 元素描述一個 React 組件時(就像上面的 React 元素同樣),React 使用該組件將描述替換爲組件返回的內容。這時它將會爲基於類的組件建立一個實例,並將該實例的引用保留在內存中。它不會爲基於函數的組件建立任何內容。它只是調用它們。

從 HelloMessage 組件返回的是一個描述 React.Fragment 組件的 React 元素。

回答問題:React.Fragment 是什麼?
React 會持續不斷的減小這些組件的未知描述,直到只存在有效的 DOM 節點。React.Fragment 的描述被翻譯成 2 個React 元素,一個描述 div ,另外一個描述 Today 組件。

</>回答問題:代碼中的 Today 什麼是?
它調用 Today 函數來找出最後一個問題。Today 函數返回描述一個 div 的 React 元素。

至此,virtual 樹中包含了全部描述 DOM 節點的 React 元素。React 經過一致性比較算法找出要在瀏覽器中更新的內容。用組件實例所轉換的樹節點保留修改該實例的能力。

相關文章
相關標籤/搜索