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のバックアップとリカバリの簡単な分析

推薦する

フロントエンド JavaScript におけるリフレクションとプロキシ

目次1. 反射とは何ですか? 2. JavaScriptで反映する2.1 Reflect.get(タ...

Linux ユーザーとグループのコマンド例分析 [切り替え、ユーザーの追加、権限制御など]

この記事では、Linux のユーザーおよびグループのコマンドについて例を挙げて説明します。ご参考まで...

サーバーの購入と初期構築方法

しばらくサーバーいじってなかったけど、やることがなくなったのでモバイルワークスに行って海外サーバーを...

mysql5.7.24 バージョンのインストール手順と解凍時に発生した問題の概要

1. ダウンロード参考: 2. D:\MySQL\mysql-5.7.24 などの固定の場所に解凍し...

Vue のキーボードイベント監視の概要

キー修飾子キーボード イベントをリッスンする場合、詳細なキーを確認する必要があることがよくあります。...

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

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

スーパーバイザーウォッチドッグの使い方を3分で学ぶ

ソフトウェアとハ​​ードウェア環境centos7.6.1810 64ビット cat /etc/red...

4つのファイル拡張子 .html、.htm、.shtml、.shtm の違い

ウェブページを作り始めたばかりの友人の多くは、拡張子が非常に多いことに気づきます。実際、htm と ...

トップ 10 Js 画像処理ライブラリ

目次導入1. 異食症2. レナ3. コンプレッサー4. ファブリック5. ぼかす6. 画像を結合する...

MySQLデータベースで列を追加、削除、変更する方法

この記事では、例を使用して、MySQL データベースの列を追加、削除、および変更する方法について説明...

docker に nacos をインストールしてデータベースを構成する詳細なチュートリアル

環境の準備 Docker環境 MySQL 5.7 (公式イメージはmysql8をサポートしていません...

HTML CSS3は画像表示効果を引き伸ばさない

1. transform 属性を使用して、画像を拡大せずに表示します (パスの問題は必要に応じて修正...

layui をベースにしたログインページの実装

この記事の例では、ログインページを実装するためのlayuiの具体的なコードを参考までに共有しています...

dockerでビルドしたnacos1.3.0の実装

1. nacosデータベースを再開します。データベース名nacos_configユーザー名とパスワー...

ログインフォームを実装するためのReactサンプルコード

Vue ユーザーとして、React を拡張する時が来ました。antd の導入、less と rout...