小さな React ChSX を構築する

Mary-Kate Olsen
リリース: 2024-10-20 18:29:30
オリジナル
311 人が閲覧しました

Build a Tiny React ChSX

このシリーズでは、React と機能的に似た小さなフロントエンド フレームワークを構築し、React が内部でどのように動作するかを説明します。この章では JSX について説明します。

ランタイムとして Bun を使用します。ノードには、typescript とコンパイル用の追加の構成が必要な場合があります。

このチュートリアルはこのチュートリアルに基づいていますが、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. 要素の小道具。これは要素のプロパティを含むオブジェクトです。たとえば、上記の h1 要素の className は、greeting.
  3. です。
  4. 要素の子。これは文字列または要素にすることができます。このパラメーターは、関数シグネチャでは ...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 要素だけが表示されます。

さらに、正式名がわからない場合は、フラグメント要素 (<>) を定義することもできます。これを行うには、ファイルの先頭に次の行を追加します。

フラグメントを処理する場合、コンパイラは構成されたフラグメント ファクトリを要素作成関数のタグに取り込みます。これは、機能コンポーネントの動作と同じです。機能コンポーネントは機能をタグに受け取ります。これについては、次の章で説明します。

それでも、私たちの実装では複雑な処理は必要ありません。フラグメントに特別なタグを設定するだけです。

import { createElement as h } from './v-dom'
ログイン後にコピー

追加のコンパイラ オプション、

bun i @types/react
ログイン後にコピー

基本的に、フラグメントは空のタグを持つ単なる特別な要素です。フラグメントの作成になると、コンパイラーは jsxFragmentFactory をフェッチし、createElement の最初のパラメーターのタグ パラメーターに入れます。したがって、フラグメントを他の要素と簡単に区別できます。

"compilerOptions": {
    "jsx": "react",
    "jsxFactory": "createElement",
}
ログイン後にコピー

このコードは仮想 DOM を正しく生成します。これまでのところ、小さな反応の JSX 部分を実装しました。

脚注

ああ、これが第 3 章の著者です。実際、現在の JSX 実装は完璧ではありません。第三章で修正します。現在、
のような構文はサポートされていません。

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

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

console.log(App());
ログイン後にコピー

これは、マップが配列を返すのに対して、すべての {} が 1 つの子として扱われるためです。したがって、ネストされた子が存在します。

また、機能コンポーネントはまだサポートされていませんでした。これについては次の章で説明します。

現在のものに従って、後で修正することができます。ご迷惑をおかけして申し訳ございません。

以上が小さな React ChSX を構築するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート