このシリーズでは、React と機能的に似た小さなフロントエンド フレームワークを構築し、React が内部でどのように動作するかを説明します。この章では JSX について説明します。
ランタイムとして Bun を使用します。ノードには、typescript とコンパイル用の追加の構成が必要な場合があります。
このチュートリアルはこのチュートリアルに基づいていますが、JSX、typescript を使用し、より簡単に実装できます。私の GitHub リポジトリでメモとコードをチェックアウトできます。
さて、さらに深く進む前に、まず、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 関数は次の引数を順番に受け取ります。
簡単な仕事だと思いませんか?それでは、やってみましょう。
コンパイルの際、使用する関数を指定できます。デフォルトでは、関数は 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 サイトの他の関連記事を参照してください。