プログラマーが最も嫌うことは、ドキュメントを書くことと、他の人がドキュメントを書かないことです。 Vue コンポーネントに基づいて直接ドキュメントを生成する方法はありますか?もちろんありますよ。ただし、サードパーティのアプリケーションは既存のプロジェクトと組み合わせて使用できない場合があり、抽出された情報をマークするために追加の注釈が必要になることがよくあります。サードパーティを利用する際によくある問題
諺にあるように、DIY は繁栄をもたらします。独自の Vue ドキュメント生成ツールを作成し、独自のプロジェクトと組み合わせて使用してください。コンポーネント ドキュメントでは通常、コンポーネント名と説明 (name)、コンポーネント プロパティ (props)、コンポーネント メソッド (methods)、コンポーネント イベント (event)、スロット (slot)、およびこれらの部分に関するコメントを指定して、説明情報を生成する必要があります。次に、いくつかの部分の抽出を段階的に実装します。 .vue ファイルの解析通常、.vue ファイルは、テンプレート、スクリプト、スタイルの 3 つの部分に分かれています。スタイル部分の内容は必要ないので、テンプレートとスクリプトの内容を個別に抽出する必要があります。 Vue は、Vue 解析専用の Vue-template-compiler ライブラリを公式に開発しました。これを直接使用して、.vue ファイルを解析および抽出できます。Vue-template-compiler は、元の Vue ファイルを処理するための parseComponent メソッドを提供します。 const コンパイラ = require('vue-template-compiler') const 結果 = コンパイラー.parseComponent(vueStr, [オプション]) // parseComponentはテンプレート、スクリプト、スタイルコンテンツを返します。 エクスポートインターフェースSFCDescriptor { テンプレート: SFCBlock | 未定義; スクリプト: SFCBlock | 未定義; スタイル: SFCBlock[]; カスタムブロック: SFCBlock[]; } 各部分のテキストを取得した後、それを ast (抽象構文木) に変換する必要があります。テンプレート部分は、Vue-template-compiler が提供する compile メソッドを直接使用して ast を生成できます。スクリプト部分は、他のメソッドを使用して ast を生成する必要があります。ここでは、js テキストを処理するために babel モジュールを使用しています。 const コンパイラ = require('vue-template-compiler') //vueStr .vue ファイルの内容 const vue =compiler.parseComponent(vueStr) //HTML部分のASTを生成する テンプレートをcompiler.compile(vue.template.content, { 空白を保持: false、 comments: true // コメント情報を生成する}) js テキスト コンテンツを処理するために、@babel/parser (Babel パーサー、Babel で使用される JavaScript パーサー) を使用します。 const parse = require('@babel/parser'); //js 部分の ast を生成 jsAst = parse.parse(vue.script.content, { とします。 どこでもインポートエクスポートを許可: true }) 文書情報を抽出する前のステップのファイル解析作業により、スクリプト内の Vue テンプレート ast と js ast を正常に取得できました。次のステップは、それらから必要な情報を取得することです。ここでは、js ast をトラバースするためのノード ツールである @babel/traverse ツールを使用する必要があります。ここでは、ast の生成されたコンテンツを表示できます。これは、さまざまなノード情報を表示するのに便利です。 traverse は '@babel/traverse' を必要とします。 トラバース.default(jsAst, { enter(path){ // 開始}, //カスタムノードをサポートします。たとえば、ノードタイプが ExportDefaultDeclaration の場合は、このメソッドを削除します。ExportDefaultDeclaration(){ } }) コンポーネント名、説明、プロパティ、メソッド、モデルを抽出しますエクスポート デフォルトによって生成される対応するノード タイプは ExportDefaultDeclaration です。宣言属性は対応するコンポーネントのオプションです。宣言属性を走査することで、名前、プロパティ、メソッド、モデルなどのノード情報を取得できます。 例 コンポーネント情報 = {} トラバース.default(jsAst, { エクスポートデフォルト宣言(パス){ path.node.declaration.properties.forEach(item => { スイッチ (アイテム.キー.名前) { ケース 'props': componentInfo.props = extractProps(item) // プロパティを抽出 壊す; ケース「メソッド」: componentInfo.methods = extractMethods(item) // メソッドを抽出 壊す ケース '名前': componentInfo.name = item.value.value // コンポーネント名を取得 ケース 'モデル': componentInfo.model = extractModel(item) // モデルを抽出 壊す デフォルト: 壊す; } }); } }) 抜粋の説明js 内のコメントは、単一行タイプと複数行タイプに分かれています。 ast を生成すると、異なるタイプも生成されます。以下の例を参照してください。 /** *複数行のメモ* ドキュメント情報をアップロードするために使用*/ // 単一行コメント export default { } // コメント終了 CommentBlock と CommentLine の 2 種類のノードがあることがわかります。先頭のコメントは leadingComments に配置され、下部のコメントは trailingComments に配置されます。 通常、コンポーネントの説明コメントはエクスポートのデフォルトに配置され、コメント情報は単純に抽出されます。 // ExportDefaultDeclaration 次のコードを挿入します if (path.node.leadingComments) { コンポーネント情報.desc = path.node.leadingComments.map(item => { if (item.type === 'コメント行') { アイテム.値.トリム() を返す } それ以外 { item.value.split('\n').map(item => item.replace(/[\s\*]/g, '')).filter(Boolean) を返します。 } }).toString() } 抽出方法メソッド内のコメントには、出力パラメータ、入力パラメータ、および追加処理を必要とするその他の情報の追加説明が必要であるため、jsdoc コメント標準は依然として比較的人気があります。ここでは、ニーズに応じて抽出ルールを定義できます。また、非同期関数であるかどうかを識別するために async を抽出する必要もあります。 /** * メソッドの説明 * @param {Bool} 型パラメータの説明 * @returns 戻り値の説明 */ 小道具の抽出プロパティの抽出では、以下の状況を区別する必要があります。デフォルトとバリデーターの抽出はまだ少し面倒です。バリデーターの検証はコメントの簡単な記述で抽出できますが、デフォルトの処理は簡単ではありません。 { propA: Number, // 型のみ propB: [String, Number], // 型のみだが複数をサポート propC: { タイプ: 文字列、 必須: true }, プロップD: { タイプ: 数値、 デフォルト: 100 // デフォルト値付き}, プロップE: { タイプ: オブジェクト、 default () { // デフォルト値は関数が返す必要があります return { message: 'hello' } } }, プロップF: { default: function () { // デフォルト値では、関数は上記のデフォルトとは異なる ast ノード型を返す必要があります return { message: 'hello' } } バリデータ: function (value) { // チェック return ['success', 'warning', 'danger'].indexOf(value) !== -1 } } } ここでは、@babel/generator を使用してデフォルトのコードを変換し、eval を介して関数呼び出しに変換してデフォルト値を返します。 types は、ノード タイプを決定するために使用される @babel/types モジュールです。 // Propsのデフォルト値を取得する function getDefaultVal (node) { type.isRegExpLiteral(node) || types.isBooleanLiteral(node) || types.isNumericLiteral(node) || types.isStringLiteral(node) の場合 { ノード値を返す } そうでない場合 (types.isFunctionExpression(node) || types.isArrowFunctionExpression(node) || types.isObjectMethod(node)) { 試す { code = generate.default(types.isObjectMethod(node) ? node.body : node).code とします。 fun = eval(**0,${types.isObjectMethod(node) ? 'function ()' : ''} $[code]**) とします。 JSON.stringify(fun()) を返す } キャッチ(エラー){ } } } モデルの抽出これは比較的簡単で、直接取得することができます。 コンポーネントイベントの抽出コンポーネントのイベントは、対応するノードから直接取得することはできません。イベントの位置は、$emit メソッドを通じてのみ特定できます。トラバースでは、MemberExpress (複合型ノード) を使用し、ノード上の属性名が $emit であるかどうかでイベントかどうかを判断できます。 イベント名は MemberExpress 親の引数にあり、コメントは 1 つ上のレベルにあることがわかります。 const extractEvents = (パス) => { // 最初の要素はイベント名です const eventName = path.parent.arguments[0]; コメントを path.parentPath.parent.leadingComments とします。 戻る { 名前: イベント名.値、 説明: コメント? comments.map(item => item.value.trim()).toString() : '——' } } メンバー式 (パス) { // イベントかどうかを判定する (path.node.property.name === '$emit')の場合{ イベントをextractEvents(パス)とします !componentInfo.events && (componentInfo.events = {}); if (componentInfo.events[イベント名]) { componentInfo.events[イベント名].desc = event.desc ? event.desc : componentInfo.events[イベント名].desc } それ以外 { componentInfo.events[イベント名] = イベント } } } イベントを正常に取得した後、イベント、プロパティ、モデルを組み合わせて、属性が .sync および v-model をサポートしているかどうかをさらに判断できます。 コンポーネントスロットの抽出まず、Vue テンプレートの ast をトラバースする関数を記述する必要があります。Vue-template-compiler は、ast をトラバースするための @babel/traverse に似た関数を提供していません。 トラバーサルテンプレート抽象ツリー関数のシンプルな実装 const traverserTemplateAst = (ast、ビジター = {}) => { 関数 traverseArray (配列、親) { 配列.forEach(子 => { トラバースノード(子、親); }); } 関数 traverseNode (ノード、親) { visitor.enter && visitor.enter(ノード、親); 訪問者[node.tag] && 訪問者[node.tag](ノード、親); node.children をトラバース配列に追加します。 visitor.exit && visitor.exit(ノード、親); } トラバースノード(ast、null); } Vue テンプレートの ast の構造は比較的明確です。js ast ほど多くの型はありません。異なるタグを区別するだけで済みます。コメントは個別のノードに分割されるため、スロット ノードを検索するときは、コメントであるかどうかを判断するために、その前の隣接ノードも検索する必要があります。 トラバーサーテンプレートAst(template.ast, { スロット (ノード、親) { !componentInfo.slots && (componentInfo.slots = {}) // ノードの位置を取得します。let index = parent.children.findIndex(item => item === node) let desc = '説明なし'、name = '-'; (インデックス>0)の場合{ タグ = 親.子[インデックス - 1] // isCommentはコメントかどうかを判定します。if (tag.isComment) { desc = タグ.テキスト.トリム() } } if (node.slotName) name = node.attrsMap.name コンポーネント情報.スロット[名前] = { 名前、 説明 } } }) 結論ここまでは、Vue コンポーネント情報の自動生成を実現しただけです。もちろん、テンプレート内のイベント $emit やレンダリング関数内のスロットなど、まだ考慮されていない状況がいくつかあります。ただし、この部分を抽出する実装は似ています。この記事のソースコードはここからご覧いただけます。 Vue コンポーネント ドキュメント生成ツール ライブラリのメソッドに関するこの記事はこれで終わりです。Vue コンポーネント ドキュメント生成ツールの関連コンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: VirtualBox は CentOS7 仮想マシンと拡張ツールをインストールします (画像とテキスト)
>>: 絵文字と問題解決のためのMySQL/Javaサーバーサポートの詳細な説明
CSS3 の角丸や影の効果を使ったページを作りたいのですが、IE ブラウザでは対応していません。こ...
ホストとコンテナ間でファイルを転送するには、コンテナの完全な ID が必要です。取得方法は以下の通り...
私はしばらく MGR と連絡を取り合ってきました。MySQL 8.0.23 の登場により、MySQL...
MySQL では、テーブルに複数のインデックスを指定できますが、ステートメントの実行時に、使用するイ...
この記事では、カルーセルマップの効果を実現するためのjsの具体的なコードを参考までに共有します。具体...
序文MySQL クエリは select コマンドを使用し、limit および offset パラメー...
この記事では、モグラ叩きゲームを実装するためのJavaScriptの具体的なコードを参考までに紹介し...
Nginx は、IP ベースの仮想ホスト構成、ポート ベースの仮想ホスト構成、ドメイン名ベースの仮想...
この質問をされたとき、私は無知で頭が真っ白になりました。もちろん、正しく答えられませんでした。私はず...
目次1. 概要2. dockerを使用してTomcatをデプロイし、Skywalkingに接続する要...
目次1. はじめに2. Viteプロジェクトを作成する1. viteをインストールする2. プロジェ...
目次序文最適化ソ連オンデマンドインポート1. ルーティングファイルでコンポーネントをオンデマンドでイ...
目次1. JavaScriptについて2. JavaScript イベントループ3. マクロタスクと...
目次概要1. 簡単な例1.サブコンポーネントの<ng-content>ディレクティブを使...
目次1. キャラクター文法パラメータ索引戻り値2. 連結文法パラメータ文字列2 [, …文字列N]戻...