JSX を使用してコンポーネント パーサー開発を構築する例

JSX を使用してコンポーネント パーサー開発を構築する例

ここでは、コンポーネント システムをゼロから構築します。まず、前回の記事「フロントエンドのコンポーネント化の基礎」から、コンポーネントはマークアップと JavaScript を通じてアクセスできる環境であることがわかりました。

したがって、最初のステップは、マークアップを使用できる環境を作成することです。ここでは、マークアップを作成する 2 つのスタイルの使用方法を学習します。

最初のものは、React と同じ JSX に基づいてコンポーネントのスタイルを設定します。 2 つ目は、Vue に似たマークアップ言語ベースのパーサーに基づいてスタイルを構築することです。

JSX環境の構築

一般的に、JSX は React の一部であると考えられています。実際、Facebook は JSX を純粋な言語拡張として定義しています。また、この JSX は他のコンポーネント システムでも使用できます。

HTML タグを素早く作成する方法としても使用できます。

プロジェクトの設定

それでは、基本から始めましょう。まず、新しいプロジェクト ディレクトリを作成する必要があります。

mkdir jsx コンポーネント

NPMを初期化する

任意のディレクトリにこのプロジェクト フォルダーを作成します。フォルダーを作成したら、そのディレクトリに入り、 npmを初期化できます。

npm 初期化

上記のコマンドを実行すると、いくつかのプロジェクト設定オプションが表示されます。必要に応じて入力してください。ただし、Enter キーを押し続けることもできます。その後、必要な学生がpackage.jsonを開いて、自分で変更することもできます。

webpackをインストールする

多くの学生は Wepack について知っているはずです。Wepack は、通常の JavaScript ファイルを、さまざまな import ファイルと require ファイルを一緒にパッケージ化できるファイルに変換するのに役立ちます。

そのため、 webpackをインストールする必要があります。もちろん、npx を使用して webpack を直接使用することも、webpack-cli をグローバルにインストールすることもできます。

ここでは、webpack-cli のグローバル インストールを使用します。

npm インストール -g webpack webpack-cli

インストールが完了したら、次のコマンドを入力して、インストールされている webpack のバージョンを確認できます。実行後にエラーがなく、バージョン番号が表示されれば、正常にインストールされたことが証明されます。

webpack --version

Babelをインストールする

JSX は babel プラグインなので、webpack、babel-loader、babel、babel プラグインを順番にインストールする必要があります。

ここで Babel を使用する別の用途があります。新しいバージョンの JavaScript を古いバージョンの JavaScript にコンパイルできるため、コードをより古いバージョンのブラウザーで実行できるようになります。

Babel をインストールするには、次のコマンドを実行するだけです。

npm インストール --save-dev webpack babel-loader

ここで注意する必要があるのは、開発依存関係に babel を追加するために--save-devを追加する必要があることです。

実行後、上の画像のようなメッセージが表示されます。

正しくインストールされたことを確認するには、プロジェクト ディレクトリのpackage.jsonを開きます。

{
 "名前": "jsx-コンポーネント",
 "バージョン": "1.0.0",
 "説明": ""、
 "メイン": "index.js",
 「スクリプト」: {
 "test": "echo \"エラー: テストが指定されていません\" && exit 1"
 },
 "著者": ""、
 「ライセンス」: 「ISC」、
 「devDependencies」: {
 "バベルローダー": "^8.1.0",
 "ウェブパック": "^5.4.0"
 }
}

OK、 devDependenciesの下に、先ほどインストールした 2 つのパッケージが確かにあることがわかります。それでも心配な場合は、 package.jsonもう一度確認してください。

webpackを設定する

この時点で、webpack を設定する必要があります。 webpack を構成するには、 webpack.config.js構成ファイルを作成する必要があります。

プロジェクトのルート ディレクトリにwebpack.config.jsファイルを作成します。

まず、webpack config は nodejs モジュールなので、その設定を記述するには module.exports を使用する必要があります。これは、初期の Node.js ツールの一般的な構成方法です。JavaScript ファイルを使用して構成するため、構成にロジックを追加できます。

モジュール.エクスポート = {}

Webpack の最も基本的なことは、エントリを設定する (エントリ ファイルを設定する) 必要があることです。ここではmain.jsをセットアップしました。

モジュール.エクスポート = {
 エントリ: "./main.js"
}

この時点で、まずルート ディレクトリにmain.jsファイルを作成できます。まず、内部に簡単なforループを追加しましょう。

// main.js ファイルの内容 for (let i of [1, 2, 3]) {
 コンソールにログ出力します。
}

このようにwebpackの基本構成は設定できました。ルートディレクトリでwebpackを実行し、 main.jsファイルをパッケージ化して見てみましょう。パッケージ化するには、次のコマンドを実行する必要があります。

ウェブパック

実行が完了すると、コマンドライン インターフェイスに上記のようなプロンプトが表示されます。

細かいことに気を配る生徒は必ず手を挙げて質問するでしょう、クラスメイト!コマンドラインにエラーがあります。黄色の部分では警告が表示されますが、問題はありません。次の構成で修正されます。

この時点で、ルート ディレクトリに新しいフォルダーdistが生成されていることがわかります。これは、webpack によってデフォルトで生成されるフォルダーです。パッケージ化されたすべての JavaScript とリソースは、デフォルトでこのフォルダーに配置されます。

ここで、 distフォルダーにパッケージ化されたmain.jsファイルがあることがわかります。これは、webpack によってパッケージ化された、私たちが作成したmain.jsです。

次にそれを開くと、babel によってコンパイルされた後の JavaScript コードが表示されます。数行のコードに多くのものが追加されていることに気づくでしょう。実際、これらを気にする必要はありません。これらはすべて Webpack の「ニャーパワー」です。

コードの最後には、先ほど書いたforループがまだ残っていますが、少し変更されているだけで、機能は同じです。

Babel-loaderをインストールする

次に、babel-loader をインストールしましょう。実は、babel-loader は babel に直接依存していないので、 @babel/core@babel/preset-env別途インストールする必要があります。インストールするには、次のコマンド ラインを実行するだけです。

npm をインストール --save-dev @babel/core @babel/preset-env 

最終結果は上記の通りであり、インストールが成功したことが証明されます。この時点で、パッケージ化時に babel-loader を使用できるように、 webpack.config.jsで設定する必要があります。

上記で設定したwebpack.config.jsentryの後に、 moduleというオプションを追加します。

次に、ビルド時に使用するrulesモジュールに追加することもできます。 rules配列型の構成であり、ここでの各ルールはtestuseで構成されます。

テスト:

  • testの値は、このルールを使用する必要があるファイルを照合するために使用される正規表現です。ここではすべての JavaScript ファイルを一致させる必要があるため、 /\.js/を使用できます。

使用:ローダー:

  • babel-loaderの名前を追加するだけです

オプション:

プリセット:

  • ここにローダーオプションがあります。ここで@babel/preset-envを追加する必要があります。

最終的に、構成ファイルは次のようになります。

モジュール.エクスポート = {
 エントリ: './main.js',
 モジュール: {
 ルール:
 {
 テスト: /\.js$/,
 使用: {
 ローダー: 'babel-loader',
 オプション:
 プリセット: ['@babel/preset-env'],
 },
 },
 },
 ]、
 },
};

これを設定したら、babel を実行して試してみます。前と同じように、コマンドラインでwebpackを実行するだけです。

設定ファイルが正しく記述されていれば、上図のような結果が表示されるはずです。

次に、 distフォルダーに移動し、コンパイルされたmain.jsを開いて、今回は babel-loader を使用した後のコンパイル結果を確認します。

コンパイル後、 for of of ループが通常のforループにコンパイルされていることがわかります。これは、babel-loader が効果的であり、新しいバージョンの JavaScript 構文を古いブラウザと互換性のある JavaScript 構文に正しく変換することを証明しています。

この時点で、JSX に必要な環境がインストールおよび構築されました。

モード設定

最後に、webpack.config.js に環境設定を追加する必要もありますが、これはオプションですが、日常の開発の利便性のために行います。

そのため、webpack.config.js にdevelopmentを使用するmodeを追加する必要があります。この構成は、開発者モードであることを示します。

一般的に、コード リポジトリに記述する webpack 構成では、このmode: 'development'構成がデフォルトで追加されます。実際にリリースする際には、 mode: 'production'に変更します。

モジュール.エクスポート = {
 エントリ: './main.js',
 モード: '開発'、
 モジュール: {
 ルール:
 {
 テスト: /\.js$/,
 使用: {
 ローダー: 'babel-loader',
 オプション:
 プリセット: ['@babel/preset-env'],
 },
 },
 },
 ]、
 },
};

変更後、 webpackを使用してコンパイルし、 main.jsの違いを確認します。

明らかに、コンパイルされたコードは 1 行に圧縮されていないことがわかりました。この方法で、webpack によって生成されたコードをデバッグできます。ここで、 main.jsのコードが文字列に変換され、 eval()関数に配置されていることがわかります。その後、デバッグ中にそれを別のファイルとして使用し、ブレークポイントデバッグを実行できます。

JSXのインポート

東風を除いて、すべて準備が整いました。最後に、JSX をどのように導入するのでしょうか?インポートする前に、現在の構成でmain.jsで JSX 構文を使用した場合に何が起こるかを確認しましょう。プログラマーとして、私たちは常に少し冒険心を持つ必要があります。

そこで、 main.jsに次のコードを追加します。

var a = <div />

それでは、思い切って webpack を実行して見てください。

よくやった!案の定、エラーが報告されました。ここでのエラーは、「小なり記号」は=の後には使用できないことを示していますが、通常の JSX 構文では、これは実際には HTML タグの「山括弧」です。JSX 構文のコンパイル プロセスがないため、JavaScript はデフォルトでこれを「小なり記号」であると想定します。

では、Webpack コンパイル プロセスで JSX 構文をサポートするにはどうすればよいでしょうか?ここで実際に最も重要なパッケージを追加する必要がありますが、このパッケージの名前は@babel/plugin-transform-react-jsxという非常に長い名前です。インストールするには、次のコマンドを実行します。

npm をインストール --save-dev @babel/plugin-transform-react-jsx

インストール後、webpack 構成にも追加する必要があります。 module内のrulesuseplugins設定を追加し、それに['@babel/plugin-transform-react-jsx']を追加する必要があります。

最終的に、webpack 構成ファイルは次のようになります。

モジュール.エクスポート = {
 エントリ: './main.js',
 モード: '開発'、
 モジュール: {
 ルール:
 {
 テスト: /\.js$/,
 使用: {
 ローダー: 'babel-loader',
 オプション:
 プリセット: ['@babel/preset-env'],
 プラグイン: ['@babel/plugin-transform-react-jsx'],
 },
 },
 },
 ]、
 },
};

設定が完了したら、webpack を実行してみましょう。この時点で、エラーは発生していないことがわかりました。これは、コードが JSX 構文の使用をサポートするようになったことを証明しています。

最後に、プログラミングの最終的な効果を見てみましょう。

evalに追加した<div/> React.createElement("div", null)の関数呼び出しに変換されていることがわかります。

それでは、 React.createElementどのように実装すべきか、またそれを独自の関数名に置き換えることができるかどうかを見てみましょう。

基本的な JSX の使用法

まず、JSX を理解してみましょう。JSX は実際にはコード構文の単なるショートカットです。前のセクションの最後で、JSX 構文がコンパイルされた後、 React.createElementへの呼び出しが表示されることを確認しました。

JSXの基礎

ここではまず、webpack の JSX プラグインを変更し、カスタム要素作成関数名を付けます。 webpack.config.js を開き、プラグイン セクションで変更します。

モジュール.エクスポート = {
 エントリ: './main.js',
 モード: '開発'、
 モジュール: {
 ルール:
 {
 テスト: /\.js$/,
 使用: {
 ローダー: 'babel-loader',
 オプション:
 プリセット: ['@babel/preset-env'],
 プラグイン: [
				[
					'@babel/plugin-transform-react-jsx',
					{ プラグマ: 'createElement' }
				]
			]、
 },
 },
 },
 ]、
 },
};

上記では、元の['@babel/plugin-transform-react-jsx']パラメータ[['@babel/plugin-transform-react-jsx', {pragma: 'createElement'}]] 。このpragmaパラメータを追加することで、作成する要素の関数名をカスタマイズできます。

この変更により、JSX は React フレームワークとは何の関係もなくなります。 webpack を実行して、最終的に生成された効果を確認してみましょう。React.createElement React.createElement createElementになることがわかります。

次に、main.js を実行するための HTML ファイルを追加して試してみます。まず、ルート ディレクトリにmain.htmlを作成し、次のコードを入力します。

<script src="./main.js"></script>

次に、この HTML ファイルを実行してブラウザで開きます。

この時点で、コンソールにエラーが表示され、 createElement未定義になります。実際、この関数はmain.jsで定義されていないため、見つかりません。

したがって、 createElement関数を自分で記述する必要があります。ルート ディレクトリでmain.jsを直接開き、前のforループを削除して、次のコードを追加します。

関数createElement() {
 戻る;
}

a = <div /> とします。

ここでは、空を返して、この関数を最初に呼び出し可能にします。 webpack で一度再コンパイルし、main.html ページを更新します。この時点ではエラーは発生せず、正常に実行できることがわかります。

createElement関数の実装

コンパイルされたコードでは、JSX 要素が createElement を呼び出すときに 2 つのパラメータを渡すことがわかります。最初の引数はdiv 、 2 番目の引数はnullです。

ここで 2 番目のパラメータがnullなのはなぜですか?実際、2 番目のパラメータは属性リストを渡すために使用されます。 main.js の div にid="a"を追加すると、最終的なコンパイルでどのような変更が行われるか確認してみましょう。

2 番目のパラメータは、Key-Value モードで保存された JavaScript オブジェクトになることがわかります。今考えてみると、JSX はそれほど神秘的なものではありません。コンパイルによって、通常記述する HTML を JavaScript オブジェクトに書き換えるだけです。一種の「[[シンタックス シュガー]]」と考えることができます。

しかし、JSX はコードの構造に影響を与えるため、通常はこれを構文糖衣とは呼びません。

次に、より複雑な JSX を記述してみましょう。元の div にいくつかの子要素を追加します。

関数createElement() {
 戻る;
}

a = (とする
 <div id="a">
 <span></span>
 <span></span>
 <span></span>
 </div>
);

最後に、次の webpack パッケージを実行して効果を確認します。

コンソールでは、最終的なコンパイル結果がcreateElement関数への再帰呼び出しであることがわかります。実際、ここにはツリー構造が形成されています。

親は第 1 レベルの div 要素であり、子は最初の createElement 関数に渡されるパラメーターです。次に、スパンに属性がないため、後続のすべての createElements の 2 番目のパラメーターはnullなります。

ここで表示されるコンパイル結果に基づいて、createElement 関数のパラメータが何であるべきかを分析できます。

  • 最初のパラメータtypeは、このタグのタイプです
  • 2番目のパラメータattribute - タグ内のすべての属性と値
  • 残りのパラメータはすべて子プロパティです...children - ここではJavaScriptの比較的新しい構文を使用します...children次のすべてのパラメータ(不定数)が配列に変換され、children変数に割り当てられることを意味します

次に、 createElement関数は次のように記述できます。

関数createElement(type, 属性, ...children) {
 戻る;
}

機能はありますが、この機能では何ができるのでしょうか?実はこの関数は何にでも使えます。DOM API のように見えるので、React とはまったく関係のないエンティティ DOM にすることもできます。

たとえば、この関数ではこのtypeelementを返すことができます。ここで、渡されたすべてのattributesこの要素に追加し、この要素に子要素を添付することができます。

要素を作成するにはcreateElement(type)を使用し、属性を追加するにはsetAttribute()を使用し、最後に子要素を追加するにはappendChild()を使用します。

関数createElement(type, 属性, ...children) {
 // 要素を作成します。let element = document.createElement(type);
 // 属性をハングする for (let attribute in attributes) {
 要素.setAttribute(属性);
 }
 // すべての子要素をハングする for (let child of children) {
 要素.appendChild(子);
 }
 //最終的に要素はノードなので、直接返すことができます return element;
}

ここではcreateElement関数のロジックを実装します。最後に、ページに DOM ノードをマウントする必要もあります。本体に直接取り付けることが可能です。

// このコードをmain.jsの末尾に追加します。let a = (
 <div id="a">
 <span></span>
 <span></span>
 <span></span>
 </div>
);

ドキュメント本体に子要素を追加します。

ここで、main.html に body タグがないことに留意してください。body 要素がないと、body にマウントできません。したがって、ここでは main.html に body 要素を追加する必要があります。

<本文></本文>
<script src="dist/main.js"></script>

さて、これで webpack でパッケージ化して効果を確認できます。

素晴らしい!ノードを生成し、ボディに取り付けることができました。しかし、 divにテキストを追加すると、テキスト ノードがcreateElement関数に渡されます。言うまでもなく、 createElement関数は現在のロジックではテキスト ノードを処理できません。

次に、テキスト ノードを処理するロジックを追加しますが、その前に div 内の span タグを削除し、テキスト「hello world」に置き換えます。

a = <div id="a">hello world</div> とします。

テキスト ノードのロジックを追加する前に、webpack を使用してパッケージ化し、具体的にどのようなエラーが報告されるかを確認しましょう。

まず、 createElement関数が呼び出される場所で、テキストが文字列として渡され、このパラメーターが子ノードを受け取り、ロジックでは DOM ノードを受け取るappendChild使用していることがわかります。明らかに、テキスト文字列はノードではないので、エラーが報告されます。

このデバッグ方法により、この機能を実装するためにロジックを追加する必要がある場所をすぐに見つけることができます。この方法は近道とも言えます。

それでは、 main.jsに戻りましょう。子ノードをアタッチする前に、次の子の型を決定します。その型が「String」文字列の場合、 createTextNode()を使用してテキスト ノードを作成し、それを親要素にアタッチします。このようにして、文字ノードの処理が完了しました。

関数createElement(type, 属性, ...children) {
 // 要素を作成します。let element = document.createElement(type);
 // 属性をハングする for (let name in attribute) {
 要素.setAttribute(名前、属性[名前]);
 }
 // すべての子要素をハングする for (let child of children) {
 if (typeof 子 === '文字列') 
		子 = document.createTextNode(子);
 要素.appendChild(子);
 }
 //最終的に要素はノードなので、直接返すことができます return element;
}

a = <div id="a">hello world</div> とします。

ドキュメント本体に子要素を追加します。

この最新のコード webpack を使用してパッケージ化すると、テキストがブラウザーに表示されることがわかります。

この時点で、 createElementすでに便利なものであり、これを使用していくつかの DOM 操作を行うことができます。 document.createElement自分で記述するという、反復的で面倒な操作を完全に置き換えることもできます。

ここで、次のことを確認できます。前の 3 つの span を div に再度追加し、各 span にテキストを追加します。 11

a = (とする
 <div id="a">
 こんにちは世界:
 <span>あ</span>
 <span>b</span>
 <span>c</span>
 </div>
);

その後、webpack を再パックすると、この DOM 操作が実際に完了できることがわかります。

現在のコードでは、すでに特定の基本的なコンポーネント機能を実現できます。

カスタムタグの実装

以前は、HTML に付属するいくつかのタグを使用していました。 div の d を大文字の D に変更するとどうなるでしょうか?

a = (とする
 <div id="a">
 こんにちは世界:
 <span>あ</span>
 <span>b</span>
 <span>c</span>
 </Div>
); 

予想どおり、エラーが報告されます。しかし、問題の根本を解明する鍵が見つかりました。ここで、div を Div に変更すると、 createElementに渡される div が文字列 'div' からDivクラスに変更されることがわかりました。

もちろん、Div クラスは JavaScript では定義されていないため、Div が定義されていないことを示すエラーが報告されます。問題がどこにあるのかがわかれば、それを解決できます。まず、未定義の問題を解決する必要があるため、まず Div クラスを作成します。

// createElment関数の後にクラスDiv {}を追加します

次に、 createElementで型判定を行う必要があります。遭遇した型が文字型である場合は、元の方法で処理します。その他の状況に遭遇した場合は、渡されたtypeをインスタンス化します。

関数createElement(type, 属性, ...children) {
 // 要素を作成する let element;
 if (typeof type === 'string') {
 要素 = document.createElement(タイプ);
 } それ以外 {
 要素 = 新しいタイプ();
 }

 // 属性をハングする for (let name in attribute) {
 要素.setAttribute(名前、属性[名前]);
 }
 // すべての子要素をハングする for (let child of children) {
 子の type が 'string' の場合、子 = document.createTextNode(child);
 要素.appendChild(子);
 }
 //最終的に要素はノードなので、直接返すことができます return element;
}

ここで別の質問があります。カスタム タグを通常の HTML タグのように動作させる方法はあるでしょうか? DOM 標準の最新バージョンでは、これを行う方法があります。カスタム タグの名前とタイプを登録するだけです。

ただし、現在のより安全なブラウジング バージョンでは、そうすることはお勧めしません。したがって、カスタム要素を使用する場合は、インターフェースを自分で記述することをお勧めします。

まず、タグ クラスを作成する必要があります。これにより、以前の通常の HTML タグの要素と同様に、任意のタグを DOM ツリーにマウントできるようになります。

以下のメソッドが含まれます。

  • mountTo() —— 後でparentノードにマウントするための要素ノードを作成する
  • setAttribute() - 要素にすべての属性を付与する
  • appendChild() - すべての子要素を要素に追加します

まず、 DivクラスにmountToメソッドを実装します。createElement に属性サブ要素をマウントするためのロジックがあるため、 setAttributeappendChildメソッドも追加する必要createElementあります。これら 2 つのメソッドが利用できない場合は、エラーが報告されます。ただし、現時点では、これら 2 つのメソッドのロジックは実装せず、メソッドの内容を空白のままにします。

クラス Div {
 属性を設定する() {}
 子要素を追加します。
 マウント先(親) {
 this.root = document.createElement('div');
 親.appendChild(this.root);
 }
}

これは実際には非常に簡単です。まず、クラスのroot属性の div 要素ノードを作成し、次にこのノードをこの要素の親にマウントします。このparentパラメータとして渡されます。

次に、元の body.appendChild コードを変更して、 mountToメソッドを使用してカスタム要素クラスをマウントします。

// document.body.appendChild(a);
ドキュメントの本文にマウントします。

現在のコードを webpack でパッケージ化して効果を確認します。

Div カスタム要素が body に正しくマウントされていることがわかります。しかし、Div 内の span タグはマウントされていません。通常の div のように動作させたい場合は、 setAttributeappendChildロジックを実装する必要があります。

次に、残りの実装ロジックを完成させてみましょう。 setAttribute と appendChild の記述を開始する前に、Div クラスにconstructorを追加する必要があります。ここで要素を作成し、それをrootにプロキシすることができます。

コンストラクタ() {
 this.root = document.createElement('div');
}

setAttributeメソッドは実際には非常に簡単です。this.root this.root使用して、DOM API でsetAttributeを呼び出すだけです。 appendChildについても同様です。最終的に、コードは次のようになります。

クラス Div {
 // コンストラクタ // DOMノードを作成するconstructor() {
 this.root = document.createElement('div');
 }
 // 要素の属性をマウントする setAttribute(name, attribute) {
 this.root.setAttribute(名前、属性);
 }
 // 要素の子要素をマウントする appendChild(child) {
 this.root.appendChild(子);
 }
 // 現在の要素をマウントする mountTo(parent) {
 親.appendChild(this.root);
 }
}

効果を確認するために、webpack でパッケージ化してみましょう。

div と span の両方が body に正常にマウントされていることがわかります。また、自作の div が正常に動作することも証明されます。

ここで別の問題が発生します。最終的にa.mountTo()を呼び出しているためです。変数aがカスタム要素ではなく、通常の HTML 要素である場合、この時点ではmountToメソッドはありません。

したがって、ここでは、通常の要素に Wrapper クラスを追加して、要素クラスの標準形式を維持できるようにする必要があります。標準インターフェースとも呼ばれます。

まずElementWrapperクラスを記述します。このクラスの内容は、実際には Div と基本的に同じです。違いは2つだけ

  1. DOM ノードを作成するときに、現在の要素名のtypeコンストラクターに渡し、このタイプを使用して DOM ノードを構築できます。
  2. 通常のタグはすべてカスタムクラスに変更されているため、appendChild はthis.root.appendChild直接使用できません。そのため、appendChild のロジックをchild.mountTo(this.root)変更する必要があります。
クラスElementWrapper {
 // コンストラクタ // DOMノードを作成するconstructor(type) {
 要素を作成します。
 }
 // 要素の属性をマウントする setAttribute(name, attribute) {
 this.root.setAttribute(名前、属性);
 }
 // 要素の子要素をマウントする appendChild(child) {
 子をマウントします(this.root);
 }
 // 現在の要素をマウントする mountTo(parent) {
 親.appendChild(this.root);
 }
}

クラス Div {
 // コンストラクタ // DOMノードを作成するconstructor() {
 this.root = document.createElement('div');
 }
 // 要素の属性をマウントする setAttribute(name, attribute) {
 this.root.setAttribute(名前、属性);
 }
 // 要素の子要素をマウントする appendChild(child) {
 子をマウントします(this.root);
 }
 // 現在の要素をマウントする mountTo(parent) {
 親.appendChild(this.root);
 }
}

ここでまだ問題が残っています。つまり、テキスト ノードに遭遇しても、それがカスタム クラスに変換されないのです。したがって、 TextWrapperと呼ばれるテキスト ノード用のものも記述する必要があります。

クラス TextWrapper {
 // コンストラクタ // DOMノードを作成するconstructor(content) {
 ルートディレクトリに document.createTextNode(content);
 }
 // 要素の属性をマウントする setAttribute(name, attribute) {
 this.root.setAttribute(名前、属性);
 }
 // 要素の子要素をマウントする appendChild(child) {
 子をマウントします(this.root);
 }
 // 現在の要素をマウントする mountTo(parent) {
 親.appendChild(this.root);
 }
}

これらの要素クラス インターフェースを使用すると、 createElement内のロジックを書き換えることができます。元のdocument.createElementdocument.createTextNodenew ElementWrapper(type)new TextWrapper(content)インスタンス化して置き換えるだけです。

関数createElement(type, 属性, ...children) {
 // 要素を作成する let element;
 if (typeof type === 'string') {
 要素 = 新しい ElementWrapper(type);
 } それ以外 {
 要素 = 新しいタイプ();
 }

 // 属性をハングする for (let name in attribute) {
 要素.setAttribute(名前、属性[名前]);
 }
 // すべての子要素をハングする for (let child of children) {
 if (typeof 子 === '文字列') 
		子 = 新しい TextWrapper(子);
 要素.appendChild(子);
 }
 //最終的に要素はノードなので、直接返すことができます return element;
}

次に、webpack でパッケージ化して確認します。

驚くことではないが、私たちの要素全体は、通常通りボディに取り付けられている。同様に、Div を div に戻しても、正常に動作します。

もちろん、通常は意味のない Div 要素は記述しません。ここでは、カルーセルのコンポーネントであるCarouselなど、コンポーネントの名前を記述します。

完全なコード - これが役に立った場合は ⭐️ をお願いします。ありがとうございます!


ここでは、私たちは互いに監督し、励まし合い、一緒に一生懸命に努力して、人生における学習の道を歩み、学習によって人生を変えていきます。

学びの道は退屈で孤独ですが、これによってより多くの仲間と励ましが得られることを願っています。一緒に応援しましょう! (๑•̀ㅂ•́)و


JSX を使用してコンポーネント パーサー (パーサー) 開発例を構築する方法については、これで終わりです。JSX コンポーネント パーサーに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vue3 のレンダリング関数における互換性のない変更の詳細な説明
  • Vueレンダリング関数renderの使い方の詳しい説明
  • Vueレンダリング機能の詳しい説明
  • Vue で jsx 構文を正しく使用する方法
  • React-vscode で jsx 構文を使用する際の問題と解決策
  • JSX を使用してカルーセル コンポーネントを実装する方法 (フロントエンドのコンポーネント化)
  • Vueコンポーネントjsx構文の具体的な使用
  • Vue jsx の使用ガイドと vue.js での jsx 構文の使用方法
  • Vue が JSX 構文をサポートする方法の詳細な説明
  • レンダリング関数と JSX の詳細

<<:  よく使うLinuxコマンドのまとめ

>>:  Alibaba Cloud CentOS 7 に yum を使用して MySQL をインストールする正しい方法 (推奨)

推薦する

Javascript で SessionStorage と LocalStorage を使用する方法

目次序文SessionStorage と LocalStorage の紹介SessionStorag...

MySQL から Excel にテーブルデータをエクスポートする際の日時形式に関する簡単な説明

最近、MySQL を使用してテーブル データを Excel ファイルにエクスポートしました。MySQ...

Day.js をベースにした JavaScript での日付処理のよりエレガントな方法

目次day.js を使用する理由モーメントデイ.js day.js がなければどうなるでしょうか? ...

vue3 再帰コンポーネントカプセル化の全プロセス記録

目次序文1. 再帰コンポーネント2. 右クリックメニューコンポーネント要約する序文今日、プロジェクト...

Windows10システムにMySQL 5.7.17をインストールする

オペレーティング システム win10 MySQL は、公式 Web サイトからダウンロードした 6...

docker compose の記述ルールについての簡単な説明

この記事ではクラスタの展開に関連する内容は紹介しませんバージョン制約Docker エンジン >...

TypeScript でオブジェクト キーの値の範囲を制限する方法

TypeScript を使用する場合、TypeScript が提供する型システムを使用してコードのあ...

Windows で MySQL 5.7.17 をインストールし、エンコードを utf8 に設定する方法

ダウンロードMySQL 公式ダウンロード、Windows (x86、64 ビット)、ZIP アーカイ...

複数のdiv内のテーブルのtdwidth設定は同じで、揃えることができません

最近、複数のdivにあるテーブルのTDを同じ幅に調整しても、揃えることができず、幅にパターンがないこ...

MySQLでconcat関数を使用する方法

以下のように表示されます。 //managefee_managefee テーブルの年と月を照会し、c...

React クラスコンポーネントのライフサイクルと実行順序

1. Reactコンポーネントを定義する2つの方法1. 関数コンポーネント。単純な関数コンポーネント...

モバイルブラウザが位置をサポートしない場合の解決策: 修正

具体的な方法は以下の通りです。 CSSコードコードをコピーコードは次のとおりです。 .wap_bot...

HTTPSの最も優れた説明

皆さんおはようございます。しばらく記事を更新していませんでした。実は、私は流行中に1か月以上家にいて...

Zabbixを介してデータベース接続情報といくつかの拡張機能をすばやく取得します

背景アプリケーション システムの数が増え続けると、当初はアラームを発していなかったアクティブ スレッ...