首頁  >  文章  >  web前端  >  建立一個小型 React ChSX

建立一個小型 React ChSX

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-10-20 18:29:30216瀏覽

Build a Tiny React ChSX

本系列將建立一個小型前端框架,其功能類似於 React,以說明 React 在幕後的工作原理。本章涵蓋 JSX。

我將使用 Bun 作為運行時。 Node 可能需要額外的配置來進行打字稿和編譯。

本教學是基於本教學課程,但使用了 JSX、Typescript 和更簡單的實作方法。您可以在我的 GitHub 儲存庫上查看註釋和程式碼。

JSX

現在,在我們進一步深入之前,讓我們先看看 React-jsx 的幾個重要元素。

如果你看過 React 元件的轉譯程式碼,你會發現它只是一堆函數呼叫。 JSX 只是 React.createElement 的語法糖。也就是說,例如,以下 JSX 程式碼:

const element = <h1 className="greeting">Hello, world!</h1>;

將被轉譯為:

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

React.createElement 會建立一個虛擬元素,這是另一個核心機制。簡單來說,虛擬元素就是虛擬DOM中的元素。虛擬 DOM 是代表實際 DOM 的東西。由於操作虛擬DOM只是操作js對象,所以比操作實際DOM快很多。我們將在下一章討論虛擬 DOM。但就目前而言,知道 JSX 只是 React.createElement 的語法糖就足夠了。

React.createElement 函數依序接受以下參數,

  1. 元素的標籤名稱。有些標籤是特殊的,如 div、span、h1 等。這些稱為內在元素。有些標籤是使用者定義的元件。
  2. 元素的 props。這是一個包含元素屬性的物件。例如,上面 h1 元素的 className 是greeting。
  3. 元素的子元素。這可以是字串或元素。請注意,該參數在函數簽名中表示為 ...children,這意味著它可以採用任意數量的參數。

這聽起來很容易,對吧?那我們就開始吧。

實施 JSX

編譯時,我們可以指定要使用的函數-預設函數是React.createElement。但我們可以使用我們自己的函數。

所以我們建立一個v-dom.ts,以便先定義虛擬元素。

export type VDomAttributes = { 
    key?: string | number
    [_: string]: string | number | boolean | Function | undefined
}

export interface VDomElement {
  kind: 'element'
  tag: string
  children?: VDomNode[]
  props?: VDomAttributes
  key: string | number | undefined
}

export type VDomNode = 
| string
| VDomElement

請注意,我們在每個節點中都有一個關鍵欄位(節點只是文字或元素的名稱)。這是為了和解,我們將在下一章中討論。您現在可以安全地忽略它。

現在我們可以實作createElement函數了。我們把它放在同一個文件中。

export function createElement(tag: string, props: VDomAttributes, ...children: VDomNode[]): VDomElement {
  console.log('createElement', tag, props, children)
    return {
        kind: 'element',
        tag,
        children,
        props,
        key: props?.key ?? undefined
    }
}

現在我們指示編譯器使用這個函數。我們可以透過將以下行新增到文件頂部來做到這一點。

const element = <h1 className="greeting">Hello, world!</h1>;

請注意,由於我們採用React標準,因此我們需要引入React類型定義。我們可以透過將以下行新增到文件頂部來做到這一點。

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

然後在 tsconfig.json 中,我們將以下行新增至 compilerOptions 欄位。

export type VDomAttributes = { 
    key?: string | number
    [_: string]: string | number | boolean | Function | undefined
}

export interface VDomElement {
  kind: 'element'
  tag: string
  children?: VDomNode[]
  props?: VDomAttributes
  key: string | number | undefined
}

export type VDomNode = 
| string
| VDomElement

現在,我們可以看看我們建立的虛擬元素。

export function createElement(tag: string, props: VDomAttributes, ...children: VDomNode[]): VDomElement {
  console.log('createElement', tag, props, children)
    return {
        kind: 'element',
        tag,
        children,
        props,
        key: props?.key ?? undefined
    }
}

您將看到我們基於 JSX 程式碼定義的虛擬 dom 元素。

此外,如果您不知道它的正式名稱,我們也可以定義一個片段元素 - >。我們可以透過將以下行新增到文件頂部來做到這一點。

在處理fragment時,編譯器會將配置好的fragment工廠帶到元素建立函數中的標籤中。這與函數式元件的工作方式相同——函數式元件會將函數傳遞給標籤,我們將在下一章中示範這一點。

儘管如此,在我們的實作中,不需要進行複雜的處理 - 我們只需要為片段設定一個特殊的標籤。

import { createElement as h } from './v-dom'

額外的編譯器選項,

bun i @types/react

基本上,fragment 只是一個有空標籤的特殊元素。當建立fragment時,編譯器會取得jsxFragmentFactory並將其放入createElement第一個參數的tag參數中。所以我們可以很容易地將片段與其他元素區分開來。

"compilerOptions": {
    "jsx": "react",
    "jsxFactory": "createElement",
}

此程式碼將正確產生虛擬 DOM。到目前為止,我們已經實作了小型 React 的 JSX 部分。

註腳

呃,這是第三章的作者。事實上,目前 JSX 的實現並不完美。我們將在第三章修復它。現在它不支援諸如
之類的語法

import { createElement } from "./v-dom";

function App() {
    return <div>
        <h1>a</h1>
        <h2>b</h2>
    </div>
}

console.log(App());

這是因為每個 {} 都被視為一個子項,而映射則傳回一個陣列。所以它會有嵌套的孩子。

此外,我們還不支援功能組件,這將在下一章中介紹。

您可以按照目前的方式進行操作,稍後再修復。抱歉造成不便。

以上是建立一個小型 React ChSX的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn