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

做者:Samer Buna

翻譯:瘋狂的技術宅javascript

原文:https://medium.com/edge-coder...html

未經容許嚴禁轉載前端

這道題的答案有點複雜。java

首先要搞清楚 elementcomponent 是否是一回事?

Image for post

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

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

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

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

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

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

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

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

最重要的是,ReactDOM 不會在瀏覽器中渲染組件,也不會渲染元素(這裏的術語元素表明 React.createElement 的返回值)。它也不渲染實例。 它只渲染 DOM 元素。

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

What’s the story here?

這是什麼故事?

每一個 React 應用都從一個使用 React elementrender 調用開始。下面以 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 經過一致性比較算法找出要在瀏覽器中更新的內容。用組件實例所轉換的樹節點保留修改該實例的能力。

173382ede7319973.gif


本文首發微信公衆號:前端先鋒

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎繼續閱讀本專欄其它高贊文章:


相關文章
相關標籤/搜索