切換語言為:簡體
React元件為什麼需要用標籤包裹?return為什麼加()?

React元件為什麼需要用標籤包裹?return為什麼加()?

  • 爱糖宝
  • 2024-09-06
  • 2054
  • 0
  • 0

前言

這次準備介紹關於react的兩個新生開發過程中時不時會犯錯或者不理解的兩個小知識點:

1. React元件為什麼需要用標籤包裹?

2. React中return為什麼加()?

React元件為什麼需要用標籤包裹?

看這樣一段程式碼:

function App() {
  return (
    <h1>Hello CodeSandbox</h1>
    <h2>Start editing to see some magic happen!</h2>
  );
}

結果報錯了

React元件為什麼需要用標籤包裹?return為什麼加()?

錯誤:JSX元素必須被一個可閉合標籤包裹

相信不少同學剛開始學習react的時候都編寫過類似的程式碼,但大家有想過為什麼會報這樣的錯嗎?以及這樣設計的目的是什麼? 不瞭解也沒有關係,接下來讓我們一起逐步解密~

再此之前先來補充React.createElementJSX的關係

React.createElement與JSX

JSX是React.createElement的語法糖

一段常見的jsx程式碼

// 部分jsx
<header className="App-header">
  <h1>哈嘍</h1>
</header>

jsx程式碼會被編譯成React.createElement函式組成的js程式碼

在元件中,需要被渲染的內容是用React.createElement(component, props, ...children) 宣告的,而 JSX 正是React.createElement函式的語法糖,JSX 會被編譯為 React.createElement()

但瀏覽器本身不支援 JSX,所以在應用釋出上線前,JSX 原始碼需要工具編譯成由若干createElement函式組成的 JS 程式碼,然後才能在瀏覽器中正常執行。JSX 需要被編譯,而編譯這個動作就是由 Babel 來完成的。

Babel編譯成 JS 就會變成:

React.createElement("header", {className: "App-header"},
  React.createElement("h1", null, "哈嘍")
);

React.createElement的基本用法

React.createElement(component, props, ...children) 接受至少三個引數:

  1. type: 字串(代表 HTML 標籤)或 React 元件(函式元件或類元件)。

  2. props: 物件,包含了該元素的屬性。傳遞給元素的屬性在元件中可透過 this.props 或 props 訪問。

  3. ...children: 其餘引數都會作為子節點(children)處理。這可以是更多的元素,字串,數字等。

單根節點思想

當React在處理渲染一個元件的時候,它需要每個元件返回一個單一的根節點。結合上述的程式碼,我們可以得到:

const element = (
<div>
  <h1>Hello CodeSandbox</h1>
  <h2 className='title'>Start editing to see some magic happen!</h2>
</div>
)

// 上述JSX最終會轉化為⬇️
const element = React.createElement(
'div',
null,
React.createElement('h1', null, 'Hello CodeSandbox'),
React.createElement('h2', { className='title' }, 'Start editing to see some magic happen!')
)

綜上所述,前言中的報錯是因為React.createElement設計時是以單節點為基礎的,所以同時傳入多個節點會發生報錯。

為什麼設計React.createElement時是以單節點為基礎的?

接下來我想請大家跟我一起設想一個場景⬇️

首先,請大家拋棄react語法,用原生JS去思考這個問題。

現在有一個列表頁,存在著3條資料,我點選了搜尋,發現當前頁面新增了4條資料,總共7條資料,這個時候你作為開發者,該怎麼去更新dom呢?

這個時候你可能脫口而出,將這4條資料一條條塞進去,但大家應該都明白,每次操作dom的效能開銷是很大的,需要進行dom插入(進行dom樹的搜尋) ,且會引起頁面的迴流重繪。如果進行多次操作,效能開銷就會成倍增長。

現在你應該想到了,那我一次性把這4條資料的dom都塞進去,不就操作一次dom了嗎?首先恭喜你回答正確,但可以再思考一下,我們怎麼做到將4個dom一次性插入呢?原生js可沒有類似的api支援你做到這一點,所以我們是不是需要將這多個dom合併成一個單一節點?這就是React的單節點思想

所以我們之所以用標籤包裹react元件的重要原因。

React元件中return為什麼加()?

react有這麼一個規則:

例如:

function Component() {
  return 
    <div>{/*假設這行JSX語句很長*/}</div>;
}

放到編譯器裡會生成:

function Component() {
  return;
  React.createElement("div", null);
}

發現了沒有

這都還沒走到 React.createElement就被return了

爲了修正這個問題,我們需要為 JSX 加上括號:

function Component() {
  return (
    <div>{/*假設這行JSX語句很長,爲了提升一些程式碼可讀性,特地換行*/}</div>
  );
}

再次編譯:

function Component() {
  return React.createElement("div", null);
}

這纔是我們最終想要的效果了~

原因如下:

JavaScript會自動在每行的末尾新增分號,如果return語句後沒有使用括號,就會在它的末尾自動插入一個分號(;),從而導致語法錯誤。透過使用括號,可以確保return語句作為一個整體被正確解析,避免因為自動插入分號而導致的bug。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.