Vueコンポーネントドキュメント生成ツールライブラリのメソッド

Vueコンポーネントドキュメント生成ツールライブラリのメソッド

プログラマーが最も嫌うことは、ドキュメントを書くことと、他の人がドキュメントを書かないことです。 Vue コンポーネントに基づいて直接ドキュメントを生成する方法はありますか?もちろんありますよ。ただし、サードパーティのアプリケーションは既存のプロジェクトと組み合わせて使用​​できない場合があり、抽出された情報をマークするために追加の注釈が必要になることがよくあります。サードパーティを利用する際によくある問題

  • ドキュメント抽出情報は包括的ではありません。抽出する必要がある情報があるかもしれませんが、サポートされていません。この場合、サードパーティのプラグインのソースコードのみを変更できます。
  • メソッドをマークするには、追加のアノテーション情報が必要です。たとえば、vuese はメソッド情報を提供するために、メソッドを @vuese、@arg などでマークする必要があります。

諺にあるように、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 をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • コンポーネントのカプセル化からの Vue スコープ スロットの実装
  • Vue 2.0 でモデルコンポーネントをカプセル化する方法
  • Vueコンポーネントドキュメント生成ノートの詳細な説明

<<:  VirtualBox は CentOS7 仮想マシンと拡張ツールをインストールします (画像とテキスト)

>>:  絵文字と問題解決のためのMySQL/Javaサーバーサポートの詳細な説明

推薦する

JavaScript はドラッグ可能なモーダルボックスを実装します

この記事では、ドラッグ可能なモーダルボックスを実装するためのJavaScriptの具体的なコードを参...

MySQLは変数を使用してさまざまなソートを実装します

コアコード -- 以下では、MySQLでのソート列の実装を示します -- テストデータ CREATE...

WeChatアプレットはシンプルな手書き署名コンポーネントを実装します

目次背景:必要:効果1. アイデア2. 実装1. ページとスタイル2. 初期化3. クリックすると4...

Vue の DOM の非同期更新の簡単な分析

目次Vue が DOM を非同期更新する原理1 実際の DOM 要素を取得できるのはいつですか? 2...

Vueは移動可能なフローティングボタンを実装します

この記事の例では、どこにでも移動できるフローティングボタンを実現するためのVueの具体的なコードを共...

Vueでlessを使用する問題を解決する

1. less依存関係をインストールします: npm install less less-loade...

MySql 5.7.21 無料インストール バージョンの構成方法 (Win10 の場合)

1.インストールしたい場所に解凍し、my.iniファイルを作成します。 my.iniの内容は次のと...

MySQLの自動増分主キーの実装の詳細な説明

目次1. 自己増分値はどこに保存されますか? 2. 自己価値修正メカニズム3. 自動増分値を変更する...

Linux での Nginx アンチホットリンクと最適化の実装コード

バージョン番号を非表示バージョン番号は非表示になっていません。セキュリティを強化するために、バージョ...

WeChatアプレットはふるいを振る効果を実現

この記事では、WeChatアプレットの具体的なコードを参考までに共有します。具体的な内容は次のとおり...

Alibaba Cloud で静的ウェブサイトを素早く構築する方法

序文:ジュニアプログラマーとして、私は自分自身の個人ウェブサイトを構築し、それを他の人に見せることを...

非表示のフォームテキストを表示するJavaScript

この記事では、フォームの隠しテキストを表示するためのJavaScriptの具体的なコードを参考までに...

MySQL クエリ フィールド タイプが json の場合の 2 つのクエリ メソッド

テーブル構造は次のとおりです。 id varchar(32) 情報JSONデータ: id = 1 i...

ホームページのデザインはウェブデザイナーのレベルを最もよく反映する

私がこれまで携わってきた多くのプロジェクトでは、基本的に避けられない悪循環がありました。それは、ホー...

MySQL 数十億のデータのインポート、エクスポート、移行に関するメモ

最近はMySQLのメモをたくさん取っていますが、それは主に会社のOracleが比較的安定していてメン...