Vue プロジェクトにインターフェース リスニング マスクを追加する方法

Vue プロジェクトにインターフェース リスニング マスクを追加する方法

1. 事業背景

マスク レイヤーを使用してユーザーの異常な操作を遮断する方法は、フロントエンドでよく使用される方法です。ただし、一部のプロジェクトではマスク レイヤーが均一に管理されていないため、次のような問題が発生します。
(1)すべてのビジネスコンポーネントはマスクレイヤーコンポーネントを導入する必要があります。つまり、各.vueビジネスコンポーネントはテンプレートにマスクコンポーネントを導入します。コンポーネントがプロジェクトの隅々まで存在し、管理に役立たず、コードが極めて冗長になっています。
(2)マスクコンポーネントは業務全体に散在しているため、マスクレイヤーを表示するかどうかを制御する変数も業務コンポーネント内に散在している。たとえば、maskShow を使用してマスク レイヤーを表示するかどうかを制御すると、より複雑なプロジェクトでは 200 を超える maskShow 変数が生成されます。
(3) maskShowが多すぎて、業務に統合されています。同時に、maskShow変数はインターフェースのコールバック関数に記述されることが多く、変数の変更を忘れて、マスクレイヤーを表示するかどうかの論理エラーが発生することがよくあります。
(4) プロジェクトはローカルでデバッグされることが多いが、実際にはオンラインで実行される。(3) の問題はローカルでは検証できないことが多い。これらの問題は、オンラインネットワーク環境が悪い場合によく発生するためです。例えば、ボタンを押した後、再度クリックするにはインターフェースが戻るまで待つ必要がありますが、ローカルの戻り速度の方が速いため、マスクレイヤーの追加を忘れても問題ありません。しかし、オンラインでネットワークに問題がある場合は、この問題が発生しやすく、一度発生すると原因の特定が難しく、作業効率に大きな影響を与えます。

2. 問題分析

上記のような背景から、実際のプロジェクトでは管理用に共通のマスク レイヤー コンポーネントを追加することが合理的です。分析後、次の問題を解決する必要があります。
(1)マスクレイヤーの表示と閉じのタイミング
(2)マスク部品の設計
(3)結合を生じさせずにコンポーネントをプロジェクトにエレガントに導入する方法。
(4)大規模な問題を起こさずに、既存のプロジェクトでオリジナルのmaskShowメソッドを段階的に置き換える方法。
(5)詳細

コンポーネント設計

1.マスクレイヤーが表示されて閉じるとき

この問題はさまざまなビジネスニーズに応じて決定されますが、著者は、ほとんどのマスクの表示と閉じ方は主にインターフェイスの要求と戻りに依存すると考えています。インターフェイスが要求保留状態にある場合、マスクレイヤーが表示され、すべてのインターフェイスが戻るとマスクが閉じられます。この記事では主に、インターフェース要求のマスキングの問題を解決します。ts で記述されており、すべての詳細が記載されているわけではありません。

2. マスク部品の設計

Mask コンポーネントは、クラス内の詳細を保護するクラスです。
(1)このクラスの主な機能は、マスクレイヤーの追加と削除、現在のリクエストインターフェースのURLの送信です。

クラスマスク{
 // マスクレイヤーを表示する appendMask(url: string): void{}

 // マスクレイヤーを削除します。removeMaskl(url: string): void{}
}

(2)マスクレイヤー関数を追加し、リクエストがあったときにその関数を呼び出し、現在のインターフェースURLを渡します。保留中のリクエストがあるかどうかを監視するために、関数内に監視オブジェクトが維持されます。このオブジェクトの値は、このインターフェースの保留状態の数です。マスク ビュー コンポーネントが Vue プロトタイプ チェーンにマウントされていると想定し、マウントされていない場合はコンポーネントの上に導入するだけです。

//リスニングオブジェクトのデータ型を定義するインターフェイス HTTPDictInterface {
 [インデックス: 文字列]: 数値;
}

追加マスク(url: 文字列): void{ 

 if (!this.monitorHTTPDict[url]) {
 this.monitorHTTPDict[url] = 0;
 }
 this.monitorHTTPDict[url] += 1;

 // 監視インターフェースがある場合はマスクレイヤーを表示します if(!this.mask && Object.keys(this.monitorHTTPDict).length){

 // ボディにマスク レイヤー スタイルを追加します。$Mask はマスク レイヤー スタイル コンポーネントです。const Constructor = Vue.extend(Vue.prototype.$Mask);
 this.mask = 新しいコンストラクタ().$mount();

 document.body.appendChild(this.mask.$el);
 }
}

(3)マスク層を削除する関数。この関数は各リクエストの終了後に呼び出されます。リクエスト監視オブジェクトが空であることがわかった場合、マスク層は削除されます。保留状態のインターフェースがない場合、接続キーを削除します。オブジェクトが空でマスク レイヤーがある場合は、マスク レイヤーを削除します。

マスクを削除します(url: 文字列): void{

 // 成功したら戻ります if (this.monitorHTTPDict[monitorUrl]) {
 this.monitorHTTPDict[モニターUrl] -= 1;
 (this.monitorHTTPDict[monitorUrl] <= 0)の場合{
 this.monitorHTTPDict[monitorUrl]を削除します。
 }
 }

 // hasMask は、ページにマスクレイヤータグ要素があるかどうかを検出するために使用されます if (this.mask && this.hasMask() && !Object.keys(this.monitorHTTPDict).length) {
 document.body.removeChild(this.mask.$el);
 this.mask = null;
 }

 this.timer = null;
}

3. 結合せずにこのコンポーネントをプロジェクトにエレガントに導入する方法。

このコンポーネントを使用するには、すべてのリクエストが開始される前に appendMask 関数を呼び出し、すべてのリクエストが完了した後に removeMask 関数を呼び出す必要があります。呼び出し方法は以下の2つがあります。
(1)axiosなどのコンポーネントのコールバックを使用して関数呼び出しを完了します。ただし、このアプローチでは、Mask コンポーネント コードはプロジェクトから独立せず、特定のインターフェイス フレームワークの API に依存します。

インスタンス.インターセプター.リクエスト.使用((config) => {

 // マスクレイヤーを追加します。mask.appendMask(config.url);

 設定を返します。
});

(2)init関数を追加し、コールバックをネイティブXMLHttpRequestオブジェクトに直接挿入します。ネイティブ XMLHttpRequest 関数を変更し、イベント 'loadstart' および 'loadend' にコールバックを挿入します。loadstart によって受信されるパラメーターには現在のリクエストの URL が含まれていないため、open 関数を書き換えて、open によって受信された URL を新しい xhr オブジェクトにマウントする必要があることに注意してください。この方法は注意して使用してください。ネイティブ API を変更することは非常に危険であり、多くのコーディング標準で禁止されているため、全員がネイティブ API を書き換えると、これらのフレームワークが同時に導入されたときに競合が発生し、予期しない結果が発生します。

//パラメータを渡すことでこのメソッドを使用するかどうかを決定します init(){
 if (this.autoMonitoring){
 this.initRequestMonitor();
 }
}

// 新しい xmlhttprequest 型インターフェース NewXhrInterface は XMLHttpRequest を拡張します{
 リクエストURL?: 文字列
}

// ネイティブインジェクション initRequestMonitor(): void{

 OldXHR を window.XMLHttpRequest にします。
 maskClass: マスク = this;

 // @ts-ignore、コーディング標準ではXMLHttpRequestの変更は許可されていません
 window.XMLHttpRequest = 関数 () {

 realXHR: NewXhrInterface = new OldXHR();
 oldOpen を実行します: Function = realXHR.open;

 realXHR.open = (...args: (文字列 | ブール値 | 未定義 | null)[]): void => {

 realXHR.requestUrl = (args[1] を文字列として);
 oldOpen.apply(realXHR、引数);

 };

 realXHR.addEventListener(`loadstart`, () => {

 const requestUrl: string = (realXHR.requestUrl を文字列として);

 定数 url: 文字列 = maskClass.cleanBaseUrl(requestUrl);

 // マスクを開く maskClass.appendMask(url);
 });

 realXHR.addEventListener(`loadend`, () => {

 const responseURL: string = (realXHR を XMLHttpRequest として).responseURL;
 定数 url: 文字列 = maskClass.cleanBaseUrl(responseURL);

 // マスクを削除します maskClass.removeMask(url);
 });

 realXHR を返します。
 };
}

(3)インジェクションの使用法、initを直接呼び出します。この方法では、プロジェクトを変更するすべてのリクエストがマスクを通過することになります。

新しいマスク().init()

4. 大規模な問題を引き起こすことなく、既存のプロジェクトで元の maskShow メソッドを段階的に置き換える方法。

プロジェクト全体で直接使用すると、関係する領域が非常に広くなり、広範囲にわたって問題が発生し、逆効果になります。したがって、スムーズな移行を実現するために、段階的な置き換えアプローチを採用する必要があります。主なアイデアは、ページとブラックリストを構成することによって、どのページにコンポーネントを導入するかを決定し、各チームメンバーが自分で変更できるようにすることです。結局のところ、ページの担当者は、現在のページビジネスを最もよく知っている人です。ブラックリストにするかホワイトリストにするかは、プロジェクトの具体的な業務内容によって決まります。

// キーは監視する必要があるルーティング ページ、値は配列、配列に入力されたインターフェースは監視する必要のないブラックリスト インターフェースです。const PAGE_ONE = `/home`;
const PAGE_TWO = `/login`;
定数 HTTO_ONE = `xxx`

エクスポートconst maskUrlList = {
 [ページ 1]: [HTTO_ONE],
 [ページ2]: [],
};

appendMask メソッドは、ブラックリストに登録されたページと未構成のページをフィルタリングします。 maskUrlList は制御対象オブジェクトです。最初にページルートをチェックし、次にブラックリストがあるかどうかをチェックします。

追加マスク(url: 文字列): void{

 // 現在のページのパスを取得し、ページ パスを取得し、ハッシュ モードと履歴モードを区別します。const monitorPath: string = this.getMonitorPath();

 // maskUrlList は設定項目です。まずページルートをチェックし、次にブラックリストがあるかどうかをチェックします。if (this.maskUrlList[monitorPath]
 && !this.maskUrlList[monitorPath].includes(url)) {
 if (this.monitorHTTPDict[url] === 未定義) {
 this.monitorHTTPDict[url] = 0;
 }
 this.monitorHTTPDict[モニターUrl] += 1;
 }

 // マスクレイヤーを追加if (!this.mask && this.hasMonitorUrl()) {
 const コンストラクター = Vue.extend(Vue.prototype.$Mask);
 this.mask = 新しいコンストラクタ().$mount();

 document.body.appendChild(this.mask.$el);
 }
}

5. 詳細

(1) マスクレイヤーはレンダリング後に閉じられ、実際のマスクレイヤーの削除ロジックはタイマーに配置されます。Vue の非同期レンダリングは promise を使用するため、レンダリング後に閉じられる場合は setTimeout に配置する必要があります。これにはイベント ループに関する知識が必要です。インターフェイスが戻ったときに、ページをレンダリングする必要がある場合、Promise が非同期に実行されます。Promise はマイクロタスクであり、setTimeout はマクロタスクです。メイン スレッドが実行されると、最初にマイクロタスクが実行され、次に非同期マクロタスク setTimeout が実行されます。

//マスクレイヤーをクリアif (!this.timer) {
 this.timer = window.setTimeout(() => {

 if (this.mask && this.hasMask() && !this.hasMonitorUrl()) {
 document.body.removeChild(this.mask.$el);
 this.mask = null;
 }

 this.timer = null;

 }, 0);
}

(2)インターフェースをフィルタリングする場合は「?」、ハッシュモードでは「#」。

// リクエストインターフェースのURLを取得する
getMonitorUrl(url: 文字列): 文字列{
 const urlIndex: number = url.indexOf(`?`);
 monitorUrl: 文字列 = url;
 urlIndex !== -1 の場合 {
 monitorUrl = url.substring(0, urlIndex);
 }
 monitorUrl を返します。
}
// 現在のルートパスを取得する
getMonitorPath(): 文字列{

 const path: string = this.mode === HASH_TYPE ? window.location.hash : window.location.pathname;

 monitorPath: 文字列 = パス;

 if (this.mode === HASH_TYPE) {
 monitorPath = monitorPath.substring(path.indexOf(`#`) + 1);
 }

 // スクリーンショットのパス、リクエストパラメータの削除 const hashIndex: number = monitorPath.indexOf(`?`);

 ハッシュインデックスが -1 の場合
 monitorPath = monitorPath.substring(0, ハッシュインデックス);
 }

 monitorPath を返します。
}

(3)インターフェースフィルタリングbaseUrl注意深く見れば、axios インターフェースを使用するときに、リクエスト時に差別化されたフィルタリングを実行するため、baseUrl を取り込むかどうかを決定できることがわかります。プロジェクトの初期段階で使用方法が明確に定義されていない場合、axios を使用するには 2 つの異なる方法があります。次に、baseUrl をフィルタリングする必要があります。

// ベースURLを削除
cleanBaseUrl(fullUrl: 文字列): 文字列 {

 const baseUrlLength: 数値 = this.baseUrl.length;
 fullUrl.substring(baseUrlLength) を返します。
 
}

(4)コンポーネントの初期化:パラメータを渡してオブジェクトをインスタンス化します。

新しいマスク({
 modeType、// ハッシュまたは履歴
 autoMonitoring, // ネイティブ XMLHttpRequest オブジェクトを更新するかどうか maskUrlList, // インポートされたページとインターフェースを構成する baseUrl, // 現在のプロジェクトのベース URL
 ...
}).init()

IV. 結論

この記事では、統合マスクレイヤーの背景、問題点、設計ソリューションについて紹介します。ただし、すべての詳細が記載されているわけではなく、実際のビジネスに基づいて選択する必要があります。しかし、全体的な計画は次のように記載されています。
(1)マスクレイヤーは、一部のインターフェースが保留中のときに表示され、すべてのインターフェースが復帰した後に自動的に閉じられる必要があります。ここでのインターフェースとは、監視する必要があるインターフェースを指します。(2) コンポーネントの最も重要な2つの機能は、マスクレイヤーを追加するappendMaskとマスクレイヤーを削除するremoveMaskです。
(3)マスクを完全に独立させ、サードパーティのライブラリ(axios)からのコールバックに依存したくない場合は、XMLHttpRequestを直接書き換えることもできますが、これは非常にリスクが高いためお勧めできません。
(4)コンポーネントの交換により、チームメンバーが独自のルーティングおよびリスニングインターフェースを構成する方法が統一されます。ここでのロジックは自分で決めることができます。監視するインターフェースが多数ある場合はブラックリストを使用でき、そうでない場合はホワイトリストを使用できます。
(5)レンダリング、リクエストパラメータ、ルーティングモードを最適化しました。

Vue プロジェクトにインターフェース監視マスクを追加する方法については、これで終わりです。Vue インターフェース監視マスクに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vueはプロキシを使用してすべてのインターフェースステータスメソッドを監視します

<<:  CentOS のファイルと権限の基本操作チュートリアル

>>:  MySQL の concat 関数についての簡単な説明。MySQL でフィールドの前または後に文字列を追加する方法

推薦する

uniappとvueの違いの詳細な説明

目次1. シンプルなページの例2.uni-appはvueコンポーネントとミニプログラムネイティブコン...

Debian システムでの自動パッケージ更新の問題を解決する方法

いつから始まったのかはわかりませんが、コンピュータの電源を入れてインターネットに接続するたびに、デー...

HTML コマンドラインインターフェースの実装

HTML部分コードをコピーコードは次のとおりです。 <!DOCTYPE html> &l...

CSS を使用して 3 列のアダプティブ レイアウト (両側は固定幅、中央はアダプティブ) を実現します。

いわゆる 3 列適応レイアウトとは、両側の幅が固定され、中央のブロックの幅が適応されることを意味しま...

Linuxアカウントファイル制御管理の詳細な手順

Linux システムでは、ユーザーが手動で作成したさまざまなアカウントに加えて、システムまたはプログ...

MySQL Limitパフォーマンス最適化とページングデータパフォーマンス最適化の詳細な説明

MySQL Limit はセグメント内のデータベース データをクエリでき、主にページングで使用されま...

要素の読み込み効果を実現するための純粋なHTML+CSS

これは Element UI の読み込みコンポーネントのエフェクトです。かっこいいですね。実装してみ...

Mac に MySQL データベースをインストールし、環境変数を設定するためのグラフィック チュートリアル

目次MySQLをインストールする環境変数の設定MySQLをインストールするmysqlをダウンロードし...

MySQL で SQL 文の実行時間を表示する方法

目次1. 初期SQLの準備2.MysqlはSQL文の実行時間をチェックします3. さまざまなクエリの...

Vueでルーティング権限を動的に設定する主なアイデア

以前、インターネット上で動的ルーティング設定をいくつか見たことがありましたが、現在のプロジェクトとは...

Node.js コンソールで強調表示されたコードを印刷する方法

序文コードを実行してエラーが発生すると、エラーが出力されます。エラーにはスタック情報が含まれており、...

Alibaba Cloud ESC サーバー シングルノード MySQL の Docker デプロイメント

1. msyqlの高速バージョンをダウンロードする docker pull hub.c.163.co...

MySQL でデータ復旧に binlog を使用する方法

序文最近、オンラインでデータが誤って操作されました。データベースが直接変更されたため、それを回復する...

Linux ncコマンドの概要

NC のフルネームは Netcat (Network Knife) で、作成者は Hobbit &a...

Vue ルーター vue-router 詳細説明ガイド

中国語ドキュメント: https://router.vuejs.org/zh/ Vue Router...