DevUI で独自の Angular コンポーネント ライブラリを構築する方法

DevUI で独自の Angular コンポーネント ライブラリを構築する方法

序文

フロントエンド開発者として、会社のビジネスが発展し成長するにつれて、コンポーネントの機能と相互作用に対するビジネスの要求はますます高まり、異なる製品やチーム間での共通コンポーネントもますます増えていきます。このとき、社内使用をサポートするためにコンポーネントライブラリのセットが必要になるか、既存のコンポーネントに基づいていくつかのネイティブサードパーティライブラリを拡張またはカプセル化することができます。この記事では、独自の Angular コンポーネント ライブラリを構築する方法を段階的に説明します。

コンポーネントライブラリの作成

まず、コンポーネントの表示とリリースを管理するためにAngularプロジェクトを作成します。次のコマンドを使用して新しいプロジェクトを生成します。

ng 新しい <my-project>

プロジェクトが初期化されたら、プロジェクトに入り、次の CLI コマンドを実行して lib ディレクトリと構成を初期化し、コンポーネント ライブラリ スケルトンを生成します。

ng ライブラリを生成 <my-lib> --prefix <my-prefix>

my-libはdevuiなどの自分で指定したライブラリ名、my-prefixはd-xxxなどのコンポーネントと命令のプレフィックスで、デフォルトで生成されるディレクトリ構造は次のようになります。

angular.json 構成ファイルでは、プロジェクトの下にあるプロジェクト タイプ ライブラリの追加構成があることも確認できます。

"my-lib": {
  "プロジェクトタイプ": "ライブラリ",
  "ルート": "プロジェクト/my-lib",
  "ソースルート": "プロジェクト/my-lib/src",
  「プレフィックス」:「dev」、
  "建築家": {
    "建てる": {
      "ビルダー": "@angular-devkit/build-ng-packagr:build",
      「オプション」: {
          "tsConfig": "プロジェクト/my-lib/tsconfig.lib.json",
          "プロジェクト": "projects/my-lib/ng-package.json"
      },
  「構成」: {
    "生産": {
      "tsConfig": "プロジェクト/my-lib/tsconfig.lib.prod.json"
    }
  }
},
...

主要な構成の変更

ディレクトリレイアウトの調整

ディレクトリ構造から、デフォルトで生成されたディレクトリ構造は比較的深いことがわかります。マテリアル デザインを参考に、次のようにディレクトリ構造をカスタマイズします。

変更点:

  • my-libディレクトリの下のsrcディレクトリを削除し、srcディレクトリからtest.tsをコピーして、コンポーネントライブラリテストファイルのエントリポイントとして使用します。
  • コンポーネントをmy-libディレクトリにフラット化し、my-libディレクトリにmy-lib.module.ts(コンポーネントのインポートとエクスポートを管理するため)とindex.ts(インポートを簡素化するためにmy-lib.module.tsをエクスポート)を追加します。
  • angular.jsonのmy-libの下のsourceRootパスをmy-libを指すように変更します。

次のように変更します。

// my-lib.module.ts


'@angular/core' から NgModule をインポートします。
'@angular/common' から CommonModule をインポートします。
import { AlertModule } from 'my-lib/alert'; // ここではオンデマンドインポート方式に従ってインポートします。my-lib はリリースライブラリ名 @NgModule({ に対応します。
  インポート: [ CommonModule ],
  エクスポート: [AlertModule],
  プロバイダー: [],
})
クラス MyLibModule をエクスポートします {}


// インデックス.ts
'./my-lib.module' から * をエクスポートします。


// 角度付きJSON
"プロジェクトタイプ": "ライブラリ",
"ルート": "プロジェクト/my-lib",
"sourceRoot": "projects/my-lib", // ここでのパスは新しいディレクトリを指します "prefix": "devui"

ライブラリ構築のためのキー構成

ng-package.json 設定ファイル、Angular ライブラリがビルド時に依存する設定ファイル

{
  "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
  "dest": "../../publish",
  "ライブラリ": {
    "エントリファイル": "./index.ts"
  },
  "whitelistedNonPeerDependencies": ["lodash-es"]
}

キー設定手順:

  • dest、libビルド出力パス。ここでは、プロジェクトビルドdistディレクトリとは別の公開ディレクトリに変更します。
  • lib/entryFileは、上記のindex.tsを指すライブラリビルドエントリファイルを指定します。

whitelistedNonPeerDependencies (オプション)。コンポーネント ライブラリが lodash などのサードパーティ ライブラリに依存している場合は、ここでホワイトリストを構成する必要があります。ng-packagr は、サードパーティの依存ライブラリで複数のバージョンが競合するリスクを回避するために、ビルド時に package.json の依存関係構成をチェックします。ホワイトリストが構成されていない場合、依存関係構成があるとビルドは失敗します。

package.json 構成では、ビジネスで関連する依存関係も構成する場合は peerDependcies を使用することをお勧めします。

{
  "名前": "my-lib",
  "バージョン": "0.0.1",
  「ピア依存関係」: {
    "@angular/common": "^9.1.6",
    "@angular/core": "^9.1.6",
    "tslib": "^1.10.0"
  }
}

詳細かつ完全な設定については、公式の Angular ドキュメント https://github.com/ng-packagr/ng-packagr/blob/master/docs/DESIGN.md を参照してください。

アラートコンポーネントの開発

コンポーネント機能の紹介

DevUI コンポーネント ライブラリのアラート コンポーネントを参照して、コンポーネント ライブラリをテストするためのコンポーネントを開発します。アラート コンポーネントは主に、ユーザーが渡したタイプに応じて異なる色とアイコンを表示し、ユーザーにさまざまな警告メッセージを表示するために使用されます。視覚的な表示は次のようになります

コンポーネント構造の分解

まず、アラートコンポーネントディレクトリにどのようなファイルが含まれているかを見てみましょう。

ディレクトリ構造の説明:

  • コンポーネントは完全なモジュール(通常のビジネスモジュールと同様)であり、ユニットテストファイルが含まれています。
  • コンポーネントディレクトリには、セカンダリエントリをサポートするための package.json があります (単一のコンポーネントがオンデマンド導入をサポートします)
  • public-api.tsは、モジュール、コンポーネント、サービスなどをエクスポートするために使用されます。これは外部公開エントリポイントです。index.tsは、他のモジュールを容易にするためにpublic-apiをエクスポートします。

要点は次のとおりです。

// パッケージ.json
{
  "ngパッケージ": {
    "ライブラリ": {
      "エントリファイル": "public-api.ts"
    }
  }
}


// パブリック API.ts
/*
* パブリックAPIアラートの表面
*/
'./alert.component' から * をエクスポートします。
'./alert.module' から * をエクスポートします。

入力と出力の定義

次に、コンポーネントの実装を開始します。まず、コンポーネントの入力と出力を定義します。投影によってアラートの内容を渡します。Input パラメータは、アラートの種類、アイコンを表示するかどうか、アラートを閉じることができるかどうかの指定をサポートします。Output は、閉じた後にユーザーがロジックを処理するための閉じるコールバックを返します。

'@angular/core' から Component、Input } をインポートします。
// アラートエクスポートのオプションの種類を定義します。 type AlertType = 'success' | 'danger' | 'warning' | 'info';


@成分({
  セレクタ: 'dev-alert'、
  テンプレート URL: './alert.component.html',
  スタイル URL: ['./alert.component.scss'],
})
AlertComponentクラスをエクスポートする{
  // アラートタイプ@Input() type: AlertType = 'info';
  // ユーザー定義アイコンをサポートするためにアイコンを表示するかどうか @Input() showIcon = true;
  // @Input() を閉じることは可能ですか? closeable = false;
  // コールバックを閉じる @Output() closeEvent: EventEmitter<boolean> = new EventEmitter<boolean>();
  非表示 = false;
  コンストラクタ() {}


  近い(){
    this.closeEvent.emit(true);
    これを非表示にするには、次の手順を実行します。
  }
}

レイアウトの定義

API 定義と視覚表示に従って、ページ レイアウト構造を実装します。レイアウトには、閉じるボタン、アイコン プレースホルダー、コンテンツ投影が含まれます。コンポーネントが閉じられると、DOM がクリアされます。

<div class="dev-alert {{ type }} " *ngIf="!hide">
  <button type="button" class="dev-close" (click)="close()" *ngIf="closeable"></button>
  <span class="dev-alert-icon icon-{{ type }}" *ngIf="showIcon"></span>
  <コンテンツ></コンテンツ>
</div>

この時点で、コンポーネントのページ レイアウトとコンポーネント ロジックがカプセル化され、視覚的な表示とそれに応じたスタイル処理に基づいて開発が完了します。

アラートコンポーネントのテスト

開発リファレンスコンポーネント

コンポーネントの開発中は、ロジックをデバッグし、UI 表示をリアルタイムで調整できる必要があります。ルート ディレクトリの tsconfig.json を開き、パス マッピングを変更して、開発モードでのコンポーネントのローカル デバッグを容易にします。ここでは、my-lib はコンポーネントのソース コードを直接指しています。もちろん、ng build my-lib --watch によるデフォルト構成を使用して、ビルドされたプレリリース ファイルを指すこともできます。このとき、変更されたディレクトリ public/my-lib/* に設定する必要があります。

「パス」: {
  "my-lib": [
    「プロジェクト/my-lib/index.ts」
  ]、
  "my-lib/*": [
    「プロジェクト/my-lib/*」
  ]、
}

設定が完了したら、開発中のライブラリを npm 方式でアプリケーションで使用できます。まず、開発中のコンポーネントを app.module.ts にインポートします。ここで、my-lib.module からすべてのコンポーネントをインポートするか、AlertModule (セカンダリ エントリをサポートするように構成されています) を直接インポートできます。

'my-lib/alert' から AlertModule をインポートします。
// 'my-lib' から { MyLibModule } をインポートします。


@Ngモジュール({
  宣言: [
    アプリコンポーネント
  ]、
  輸入: [
    ブラウザモジュール、
    アプリルーティングモジュール、
    // マイライブラリモジュール
    アラートモジュール
  ]、
  プロバイダー: [],
  ブートストラップ: [AppComponent]
})
クラス AppModule をエクスポートします { }

この時点で、app.component.html ページで開発中のアラート コンポーネントを直接使用できます。

<セクション>
  <dev-alert>私はデフォルトのアラートタイプです</dev-alert>
</セクション>

ページを開くと、現在の開発の効果を確認できます。この時点で、ページのパフォーマンスに応じてスタイルとインタラクションロジックを調整できます。ここではこれ以上示しません。

ユニットテストを書く

前述のとおり、ユニット テスト ファイルがあります。コードの品質と、その後のリファクタリングされたコンポーネントの安定性を確保するために、コンポーネントを開発するときにユニット テストを追加することをお勧めします。

ディレクトリ構造を調整したので、まずは関連する設定を変更しましょう

// 角度付きJSON
"my-lib": {
  ...
  "テスト": {
    "ビルダー": "@angular-devkit/build-angular:karma",
    「オプション」: {
      "main": "projects/my-lib/test.ts", // これは調整されたファイル パスを指します "tsConfig": "projects/my-lib/tsconfig.spec.json",
      "karmaConfig": "projects/my-lib/karma.conf.js"
    }
  },
}


//my-libディレクトリのtsconfig.spec.json  


「ファイル」: [
  "test.ts" // 現在のディレクトリ内のテストエントリファイルを指します]

以下は、型が正しいかどうかを単純にテストする簡単なテストリファレンスです。テストするコンポーネントはテストファイルで定義されています。シナリオが多数ある場合は、デモを提供し、デモを直接使用してさまざまなシナリオをテストすることをお勧めします。

'@angular/core/testing' から { async、ComponentFixture、TestBed } をインポートします。


'@angular/core' から Component をインポートします。
'./alert.module' から AlertModule をインポートします。
'./alert.component' から { AlertComponent } をインポートします。
'@angular/platform-b​​rowser' から { By } をインポートします。


@成分({
  テンプレート: `
    <dev-alert [type]="type" [showIcon]= "showIcon"[closeable]="closeable" (closeEvent)="handleClose($event)">
    <span>私はアラートコンポーネントです</span>
    </開発アラート>
  `
})
クラス TestAlertComponent {
  タイプ = '情報';
  アイコンを表示 = false;
  閉じることができる = false;
  クリック数 = 0;
  ハンドルクローズ(値) {
    this.clickCount++;
  }
}


記述('AlertComponent', () => {
  コンポーネントを作成します: TestAlertComponent;
  フィクスチャを ComponentFixture<TestAlertComponent> にします。
  alertElement: HTMLElement を設定します。


  beforeEach(async(() => {
    TestBed.configureTestingModule({
      インポート: [AlertModule],
      宣言: [ TestAlertComponent ]
    })
    .compileComponents();
  }));


  それぞれの前に(() => {
    フィクスチャ = TestBed.createComponent(TestAlertComponent);
    コンポーネント = fixture.componentInstance;
    alertElement = fixture.debugElement.query(By.directive(AlertComponent)).nativeElement;
    フィクスチャ.detectChanges();
  });


  記述('アラートインスタンステスト', () => {
    it('作成すべき', () => {
      コンポーネントが真実であることを想定します。
    });
  });


  describe('アラートタイプテスト', () => {
    it('アラートには情報タイプが必要です', () => {
      期待(alertElement.querySelector('.info'))。nullではありません。
    });


    it('アラートには成功タイプが必要です', () => {
      // 型の変更が正しいかどうかを判断するために型を変更します。component.type = 'success';
      フィクスチャ.detectChanges();
      期待(alertElement.querySelector('.success'))。not.toBe(null);
    });
  }

ng test my-lib を実行することでユニット テストを実行できます。デフォルトでは、テスト結果を表示するウィンドウが開きます。

ここまででコンポーネント開発のリファレンスとテストは完了です。機能やインタラクションに問題がなければ、npm に公開する準備ができます。

詳細なテスト内容については、公式の紹介を参照してください: https://angular.cn/guide/testing

リリースコンポーネント

コンポーネントの開発が完了し、ユニット テストが定義したアクセス制御インジケーターを満たしたら、他の学生が使用できるように npm に公開できます。

まず、ng9 はデフォルトで Ivy エンジンを使用するため、コンポーネント ライブラリをビルドします。 Ivy 形式のライブラリを NPM リポジトリに公開することは公式には推奨されていません。したがって、NPM に公開する前に、Ivy の代わりに古いコンパイラとランタイムである View Engine を使用する --prod フラグを使用してビルドします。

ng ビルド my-lib --prod

ビルドが成功したら、コンポーネント ライブラリの公開を開始できます。ここでは、npm 公式リポジトリへの公開を例に説明します。

まだnpmアカウントをお持ちでない場合は、公式ウェブサイトにアクセスしてアカウントを登録し、パブリックタイプの無料アカウントを選択してください。

すでにアカウントをお持ちの場合は、まず、設定されたレジストリがnpm公式レジストリ https://registry.npmjs.org/ を指していることを確認してください。

ターミナルでnpm loginを実行して登録したユーザーにログインします。

すべての準備が完了したら、公開ディレクトリであるビルドディレクトリに移動し、npm publish --access public を実行して公開します。ライブラリ名は npm 上で空いている必要があることに注意してください。名前は、my-lib ディレクトリの package.json で変更されます。

npm 公開リファレンス: https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry

内部プライベート ライブラリの場合は、プライベート ライブラリの要件に従ってレジストリを構成するだけで、公開コマンドは同じになります。

上記は、DevUI を使用して独自の Angular コンポーネント ライブラリを構築する方法の詳細です。DevUI を使用して独自の Angular コンポーネント ライブラリを構築する方法の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • angular4 ng-content の隠しコンテンツに関する簡単な説明
  • コンポーネントにコンテンツを埋め込むための Angular2 ng-content ディレクティブについての簡単な説明
  • Angularデータバインディングとその実装の詳細な説明
  • React、Angular、Vueの3つの主要なフロントエンド技術の詳細説明
  • Angular のパフォーマンス最適化: サードパーティ コンポーネントと遅延読み込みテクノロジー
  • Angularフレームワークのビュー抽象定義の詳細な説明
  • AngularJSにおける括弧の役割の詳細な説明
  • Angularコンポーネント投影の詳細な説明

<<:  MySQL の frm ファイルからテーブル構造を復元する 3 つの方法 [推奨]

>>:  MySQL 8.0 における MySQL のインストールと新しいパスワード認証方法の詳細な説明

推薦する

Vue で親子コンポーネントの値を双方向バインドするために v-model を使用するときに発生する問題と解決策

目次シナリオ解決してみる解決するシナリオ今日、コンポーネントの双方向データバインディングにv-mod...

ウェブページのテキストデザインは、服を着た賢い女の子のようであるべきだ

<br />「この世に醜い女性はいない、あるのは怠惰な女性だけだ」これは女性の美のバイブ...

MySQL の instr を使用したファジー クエリ メソッドの紹介

MySQL の内部関数instrを使用すると、従来の like クエリ メソッドを置き換えることがで...

フロントエンドAIカットのコツ(体験談)

AI 画像の切り取りは PS と連携する必要があります。まず、スライスするレイヤーを選択し、それを...

HTML テーブルタグチュートリアル (13): 内部境界スタイル属性ルール

RULES を使用すると、テーブルの内部境界のスタイルを制御できます。基本的な構文<TABLE...

デザイン理論:テキスト表現とユーザビリティ

<br />テキストデザインでは、通常、テキストのレイアウト、つまりテキストをより美しく...

VUE+Canvasは、インゴットを受け取る富の神のゲームを実装します

前回のキャンバス ゲーム シリーズへようこそ: 《VUEがFlappy Birdを実装しました〜〜〜...

WAMPにインストールするとMySQLが起動できるが、再起動後に起動できなくなる問題の解決方法

初めてwampをインストールした後、すべてのサービスが正常に使用できますが、再起動するとwampのア...

MySQL シリーズ 8 MySQL サーバー変数

チュートリアルシリーズMySQL シリーズ: MySQL リレーショナル データベースの基本概念My...

WeChatアプレットはキャンバスを使用して時計を描画します

この記事では、キャンバスを使用してWeChatアプレットに時計を描く具体的なコードを参考までに共有し...

Vueは要素ツリーコントロールを通じてツリーテーブルを実装します

目次実装効果図依存関係をインストールするカスタムツリーコントロールその他の実装要約するVueでは、要...

CSS を使用して複数の方法で等幅レイアウトを実装するサンプルコード

この記事で説明する等幅レイアウトでは、純粋な CSS を使用して、要素の幅を手動で設定することなく、...

MySql はコミットする必要がありますか?

MySQL が挿入などの操作を実行するときにコミットする必要があるかどうかは、ストレージ エンジン...

検証例 MySQL | 同じ値を持つフィールドを更新すると、binlog に記録されます

1. はじめに数日前、開発仲間から、フィールドを同じ値に更新すると binlog が記録されるかどう...

MySql ログイン パスワードを忘れた場合とパスワードを忘れた場合の解決策

方法1: MySQL では、次のコマンド ラインで MySQL サーバーを起動することにより、アクセ...