Vue コードの読みやすさに関するいくつかの提案

Vue コードの読みやすさに関するいくつかの提案

序文:

最近、Vue プロジェクトに参加しましたが、先祖の糞の山に落ちてしまったような気がしました。保守性は言うまでもなく、可読性は極めて低いです。そこで、このコラムでは、Vue コードの可読性についていくつか提案したいと思います。提案が役に立つと思ったら、ぜひ「いいね!」してください。提案が不合理だと思うなら、ぜひコメントして批判してください。より良い提案があれば、ぜひコメントして追加してください。

1. コンポーネントをうまく活用してコードを整理する

ページのすべての実装コードを .vue ファイルに置かないでください。ページが非常に単純な場合を除き、この.vueファイル内のコードは長くて見苦しいものになります。

Vueがコンポーネントを提供する目的は、再利用のためだけではなく、コードを分割したり、コンポーネントを有効に活用してページのレンダリングと更新の速度を最適化したりするためにも使用できます。これは、Vue ページのレンダリングが更新されても、コンポーネントのpropsまたはslotによって参照されるデータが変更されない限り、ページ内のコンポーネントは更新されないためです。

以下の手順に従って、Vue ページをコンポーネントに分割し、コードをより整理することができます。

1. UIコンポーネントを抽出する

UI コンポーネントを定義するにはどうすればいいですか?個人的には、サーバー側データを処理するかどうかに基づいて、UI コンポーネントとビジネス コンポーネントを区別することをお勧めします。たとえば、読み込みポップアップ ウィンドウ、2 番目の確認ポップアップ ウィンドウ、メッセージ プロンプト ボックスなどは、UI インタラクション コンポーネントです。

UI コンポーネントを抽出した後、UI インタラクション コードとビジネス インタラクション コードを分離できます。 UI コンポーネントにビジネス コードを記述しないでください。そうしないと、UI コンポーネントを再利用できなくなります。

反例として、2 回目の確認ポップアップ ウィンドウで 2 回目の確認後に処理するビジネス コードを追加すると、UI コンポーネントを再利用できなくなります。 ElementUI のセカンダリ確認ポップアップ ウィンドウの呼び出しを模倣して、セカンダリ確認ポップアップ ウィンドウ コンポーネントを実装できます。

this.$confirm(メッセージ、タイトル、オプション)
  .then(res =>{})
  .catch(エラー =>{})

このように、then のコールバック関数内にビジネス コードを記述できます。コンポーネントのコア実装コードは次のとおりです。

//確認.vue
<テンプレート>
  <div v-show="表示">
    //...
    <div @click="ok"></div>
    <div @click="キャンセル"></div>
  </div>
</テンプレート>
<スクリプト>
エクスポートデフォルト{
  データ() {
    戻る {
      表示: 偽、
    }
  },
  メソッド: {
    わかりました() {
      this.show = false;
      これを解決します。
    },
    キャンセル() {
      this.show = false;
      これを解決します。
    },
  }
}
</スクリプト>

//index.js
'vue' から Vue をインポートします。
'./confirm.vue' からオプションをインポートします。
const Confirm = Vue.extend(オプション);
確認 = 未定義とします。
const ConfirmInit = (オプション = {}) => {
  新しい Promise を返します ((resolve, reject) => {
    オプションを解決します。
    オプション.拒否 = 拒否;
    確認 = 新しい確認({
      el: document.createElement('div'),
      データ: オプション
    })
    document.body.appendChild(確認.$el);
    Vue.nextTick(() => {
      if (確認) confirm.show = true;
    })
    確認を返す;
  })
}
Vue.prototype.$confirm = ConfirmInit;

//メイン.js
import 'components/confirm/index.js'; // 二次確認ポップアップ確認コンポーネントのグローバル登録

2. モジュールごとにビジネスコンポーネントを抽出する

ページは、ヘッダー、フッター、サイドバー、商品リスト、会員リストなど、複数の領域に分割できます。各領域は、ビジネスコンポーネントを抽出するためのモジュールとして使用できます。

3. 機能別に機能コンポーネントを抽出する

モジュールごとにビジネスコンポーネントを抽出した後でも、ビジネスコンポーネントが非常に大きい場合があるため、機能ごとに機能コンポーネントをさらに抽出する必要があります。

関数のサイズはさまざまであり、関数を抽出するときに注意すべき原則がいくつかあります。

過度に単純な関数は抽出されません。

たとえば、コレクション関数は、インターフェースを要求することによって完了できます。このような関数は抽出しないでください。特定の複雑さの論理演算を持つ関数のみを抽出できます。

関数は単一である必要があります:

機能コンポーネントは 1 つのビジネスのみを処理します。

たとえば、ファイル リーダー コンポーネントでは、ファイルを開いた後に自動的にファイルを収集する必要があります。この場合、収集ロジック コードはどこに記述すればよいでしょうか。

おそらく、コンポーネント内のファイルのオープンが成功したかどうかをリッスンするメソッドに、何も考えずにコレクション ロジック コードを記述したのでしょう。しばらくすると、コレクション ボタンをクリックする前に読み取りレコードに追加するという要件に変更されました。コンポーネント内のコードを修正しようとしたところ、別のページもこのコンポーネントを参照していることがわかったため、ビジネス シナリオを区別するためにコンポーネントに追加のパラメーターを追加する必要がありました。要件が変化するにつれて、ビジネス シナリオが重なり合い、さまざまな判断ロジックがコンポーネント コードに追加され、時間の経過とともに長くて退屈なものになりました。明らかに、このアプローチは受け入れられません。

正しい方法は、コンポーネント タグのon-fileOpen-successイベントをカスタマイズし、 handleFileOpenSuccess関数を使用してこのイベントをリッスンすることです。

<ファイルリーダー 
  @on-fileOpen-success="handleFileOpenSuccess"
>
</ファイルリーダー>

コンポーネントのファイルが正常に開かれたかどうかをリッスンするメソッドでthis.$emit('on-fileOpen-success',data)を実行してこのイベントをトリガーします。 dataファイル情報を渡すことができ、 handleFileOpenSuccess関数は収集や履歴レコードの追加と収集などのビジネス インタラクションを処理できます。このアプローチにより、ファイル リーダー コンポーネントがモノリシックになります。

機能コンポーネントにはできるだけ UI を含めず、UI 部分はスロットを通じて渡す必要があります。これにより、コンポーネントがより純粋になり、再利用しやすくなります。

たとえば、UI デザインのドラフトが変更されると、アップロード コンポーネントにアップロード アイコンを追加できなくなります。この場合、スロットを使用してアップロード アイコンを渡すことができます。

//アップロード.vue
<テンプレート>
  <div>
    <スロット名="アイコン"></スロット>
  </div>
</テンプレート>

//インデックス.vue
<テンプレート>
  <div>
    <アップロード>
      <テンプレート #アイコン>
        //アップロードアイコン</template>
    </アップロード>
  </div>
</テンプレート>

2. v-bindを使用してコンポーネントのプロパティを読みやすくする

オブジェクトのすべてのプロパティをpropとしてcomponentAに渡す場合は、パラメーターなしでv-bindを使用できます。たとえば、特定のオブジェクトparamsの場合:

パラメータ: {
  id: 1,
  名前: 'vue'
}

最適化前:

<componentA :id="params.id" :name="params.name"></componentA>

最適化後:

<componentA v-bind="params"></componentA>

3. attrsとattrsとリスナーを使用してサードパーティのコンポーネントをカプセル化する

1. $属性

サードパーティ コンポーネントをカプセル化する場合、カプセル化されたコンポーネントを通じてサードパーティ コンポーネント自体のプロパティとイベントをどのように使用するかという問題に遭遇することがよくあります。

たとえば、 Inputボックス コンポーネントmyInputelementUiコンポーネントにカプセル化し、誤ったコンテンツが入力されたときに入力ボックスの下にエラー プロンプトを表示します。

myInputコンポーネント コードは次のとおりです。

<テンプレート>
  <div>
    <el-input v-model="入力"></el-input>
    <div>{{エラーヒント}}</div>
  </div>
</テンプレート>
<スクリプト>
エクスポートデフォルト{
  小道具: {
    価値: {
      タイプ: 文字列、
      デフォルト: ''、
    },
    エラーヒント: {
      タイプ: 文字列、
      デフォルト: ''、
    }
  },
  データ() {
    戻る {
    }
  },
  計算: {
    入力: {
      得る() {
        this.valueを返す
      },
      設定(値) {
        this.$emit('input', val)
      }
    }
  }
}
</スクリプト>

myInputコンポーネントは次のように呼び出されます。ここで、 errorTip入力ボックス内の入力エラーのヒントです。

<myInput v-model="input" :errorTip="errorTip"></myInput>

入力ボックスを無効にするために、 myInputコンポーネントに disabled 属性を追加するにはどうすればよいでしょうか。ほとんどの学生はそうするでしょう。

<テンプレート>
  <div>
    <el-input v-model="入力"
      :disabled="無効"></el-input>
    <div>{{エラーヒント}}</div>
  </div>
</テンプレート>
<スクリプト>
エクスポートデフォルト{
  小道具: {
    //...
    無効:
      タイプ: ブール値、
      デフォルト: false
    }
  },
  //...
}
</スクリプト>

しばらくすると、 el-inputコンポーネントの他の属性をmyInputコンポーネントに追加する必要があります。el el-inputコンポーネントは合計で 27 個以上あります。どうすればよいでしょうか? propを使用して 1 つずつ渡す必要がありますか? これでは読みにくいだけでなく、面倒です。 $attrsを使用すると、1 つの手順で実行できます。まずはattrsの定義を見てみましょう。

$attrs:親スコープでpropとして認識されない (および取得されない) attributeバインディング ( classstyleを除く) が含まれます。コンポーネントがpropを宣言していない場合、すべての親スコープバインディング( classstyleを除く)がここに含まれ、 v-bind="$attrs " を介して内部コンポーネントに渡すことができます。

v<テンプレート>
  <div>
    <el-input v-model="入力"
      v-bind="$attrs"></el-input>
    <div>{{エラーヒント}}</div>
  </div>
</テンプレート>

これだけじゃ十分ではありませんinheritAttrsオプションをfalseに設定する必要もあります。なぜでしょうか? inheritAttrsオプションの定義を見れば、理解できるでしょう。

デフォルトでは、 propsとして認識されない親スコープのattribute attribute bindings 「フォールバック」され、子コンポーネントのルート要素に通常のHTML attributeとして適用されます。ターゲット要素または別のコンポーネントをラップするコンポーネントを作成する場合、これが必ずしも期待どおりの動作になるとは限りません。 inheritAttrs falseに設定すると、このデフォルトの動作は削除されます。これらのattribute $attrsを通じて有効にすることができ、 v-bindを通じてルート以外の要素に明示的にバインドすることができます。注: このオプションはclassstyleバインディングには影響しません。

簡単に言うと、 inheritAttrs falseに設定すると、 v-bind="$attrs " が有効になります。

<テンプレート>
  <div>
    <el-input v-model="入力"
      v-bind="$attrs"></el-input>
    <div>{{エラーヒント}}</div>
  </div>
</テンプレート>
<スクリプト>
エクスポートデフォルト{
  継承属性: false、
  小道具: {
    価値: {
      タイプ: 文字列、
      デフォルト: ''、
    },
    エラーヒント: {
      タイプ: 文字列、
      デフォルト: ''、
    }
  },
  データ() {
    戻る {
    }
  },
  計算: {
    入力: {
      得る() {
        this.valueを返す
      },
      設定(値) {
        this.$emit('input', val)
      }
    }
  }
}
</スクリプト>

このようにすることで、 el-inputコンポーネントのプロパティをmyinputコンポーネントのプロパティと明確に区​​別できるようになり、コンポーネントのpropsオプションの読みやすさが大幅に向上します。

2. $リスナー

では、 myIpputコンポーネントのel-inputコンポーネントにカスタム イベントを実装するにはどうすればよいでしょうか。最初の反応はthis.$emit。

<テンプレート>
  <div>
    <el-input v-model="入力"
      v-bind="$attrs"
      @blur="ぼかし">
    </el-input>
    <div>{{エラーヒント}}</div>
  </div>
</テンプレート>
<スクリプト>
エクスポートデフォルト{
  //...
  メソッド: {
    ぼかし(){
      this.$emit('blur')
    }
  }
}
</スクリプト>

<私の入力 
  v-model="入力"
  :errorTip="エラーヒント"
  @blur="ハンドルブラー">
</myInput>

el-inputコンポーネントには 4 つのカスタム イベントがありますが、それほど多くはありません。サードパーティのコンポーネントにさらに多くのカスタム イベントがある場合はどうすればよいでしょうか。1 つずつ追加するべきでしょうか。そうすると、不要なmethodsが大量に追加されるだけでなく、読みにくくなり、 myInput独自のmethodsと簡単に混在してしまいます。実際、 $listenersを使用すると、 1 つのステップで目的を達成できます。まず、 $listenersの定義を見てみましょう。

$listeners:親スコープ内のv-onイベント リスナーが含まれます ( .native修飾子なし)。 v-on="$listeners"を介して内部コンポーネントに渡すことができます。

<テンプレート>
  <div>
    <el-input v-model="入力"
      v-bind="$attrs"
      v-on="$リスナー">
    </el-input>
    <div>{{エラーヒント}}</div>
  </div>
</テンプレート>
<スクリプト>
エクスポートデフォルト{
  //...
}
</スクリプト>

<私の入力 
  v-model="入力"
  :errorTip="エラーヒント"
  @blur="ハンドルブラー">
</myInput>

myInputコンポーネントでは、 el-inputコンポーネントにv-on="$listeners " を追加するだけで、 el-inputコンポーネントのカスタマイズされたイベントをmyInputコンポーネントで使用できます。

これで、Vue コードの読みやすさに関する提案に関するこの記事は終了です。Vue コードの読みやすさに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • 5 分で vue-cli3 を使用してプロジェクトを作成する方法を説明します (初心者向けガイド)
  • Vueプロジェクトでlessを使用するためのヒント
  • Vue プロジェクトで TypeScript クラスを適用する方法
  • Vue.jsでタブ切り替えと色変更操作を実装する解説
  • ナビゲーションバーコンポーネントをVueでカプセル化する
  • Vuex全体のケースの詳細な説明
  • Vueのトグルボタンをクリックしてボタンを有効にし、無効にします。
  • Vueコンポーネント通信方法事例まとめ
  • Vue.js スロットにおけるスコープ付きスロットの使用法の詳細な説明

<<:  Dockerコンテナの構築と実行のプロセスの詳細な説明

>>:  MySQLのバックアップとリカバリの簡単な分析

推薦する

MySQLウィンドウ関数の具体的な使用法

目次1. ウィンドウ関数とは何ですか? 1. ウィンドウをどのように理解しますか? 2. ウィンドウ...

MySQL の sql_mode モード例の詳細な説明

この記事では、MySQL の sql_mode モードについて例を挙げて説明します。ご参考までに、詳...

ウェブページを最適化してメモリとCPUの使用率を削減

一部の Web ページは大きく見えなくても開くのに非常に時間がかかる場合があります。一方、他の We...

CSS3のtransform属性で実装される4つの機能

CSS3 では、transform 関数を使用して、テキストや画像の回転、拡大縮小、傾斜、移動という...

MySQL コール初心者が犯しがちな 11 の間違いのまとめ

序文セキュリティ部門からSQLインジェクションやXSS攻撃の脆弱性などに関する警告メールを頻繁に受け...

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

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

Dockerコンテナに入る方法と出る方法

1 Dockerサービスを開始するまず、docker サービスを開始する方法を知っておく必要がありま...

winx64 での mysql5.7.19 の基本的なインストール プロセス (詳細)

1. ダウンロード参考: https://www.jb51.net/softs/451120.ht...

初心者のためのMySQL外部キーの設定方法

目次外部キーの役割mysql 外部キー設定方法要約する外部キーの役割データの一貫性、整合性を維持し、...

VMware Workstation16 と Navicat リモート接続での Centos7 での MySQL8.0 インストール プロセス

目次1. CentOS7+MySQL8.0、yumソースインストール2. MySQLにログインしてパ...

Dockerはbusyboxを使用してベースイメージを作成します

Docker イメージの最初の行は FROM alpine などのイメージで始まりますが、最初のベー...

Reactフック入門チュートリアル

ステートフック例: 'react' から useState をインポートします。 関...

純粋な HTML ページを送信し、パラメータを渡し、ID を確認する方法

プロジェクトにはアンケートが必要ですが、クライアントはアンケートのタイトルが純粋なHTMLタグでなけ...

Linux での grep コマンドの使い方の詳細な説明

1. 公式紹介grep は Linux でよく使用されるコマンドです。これは、ファイルやテキストに対...

Ubuntu サーバーで MySQL を設定し、リモート接続を実装する方法

サーバー: Ubuntu Server 16.04 LSSクライアント: Ubuntu 16.04 ...