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初心者がよく犯す間違い

目次序文undefined と null の混同紛らわしい数値の加算と文字列の連結戻り文の改行の問題...

ハイパーリンクAタグを学ぶ

聞く: CSS を使用してハイパーリンクのスタイルを設定しましたが、ホバーしても機能しません。なぜこ...

dubbo での Zookeeper リクエストのタイムアウト問題: mysql8.0.15 に接続する mybatis+spring の構成

ここ2日間Javaを復習するつもりなので、練習にdubboを使ってショッピングモールプロジェクトを書...

ファイルのダウンロードを実現する javascript Blob オブジェクト

目次例示する1. ブロブオブジェクト2. フロントエンド3. バックエンド要約する例示する最近、ファ...

クリーンなコードのための Web デザインの 12 の法則 [グラフィック]

美しいコードは美しい Web サイトの基礎です。優れた CSS は、同様に優れた HTML の上にの...

VMware14 に CentOS 7 をインストールするグラフィック チュートリアル

CentOS の紹介CentOS は、Red Hat Linux が提供する無料で利用できるソースコ...

テキストエリアのテキスト入力領域に改行を実装する方法

textarea 入力領域でテキストを折り返す場合は、<br/> と入力すると <...

データベースクエリの最適化: サブクエリの最適化

1. 事例会社のトップ以外の従業員全員を年齢別にグループ化します。 t_emp で id が存在しな...

MySQLの高可用性アーキテクチャの詳細な説明

目次導入MySQL 高可用性マスター 1 つとバックアップ 1 つ: MySQL マスター スレーブ...

HTML/XHTML における img 画像タグの基本的な使用法の詳細な説明

画像タグは、Web ページに画像を表示するために使用されます。 HTML/XHTML 画像 <...

UbuntuはPythonスクリプトのサンプルコードを定期的に実行する

オリジナルリンク: https://vien.tech/article/157序文この記事では、Ub...

MySQL の中国語文字化け問題の解決方法

1. LinuxのMySQLで中国語の文字化けが発生する。以下の操作を実行する。 vi /etc/m...

Portainer を使用して Docker のビジュアル インターフェースを構築する方法

ポーテナーの紹介Portainer は、ステータス表示パネル、アプリケーション テンプレートの迅速な...

Oracle Rownum 書き込みに似た MySQL の詳細な例

Rownum は、Oracle での独自の書き込み方法です。Oracle では、rownum を使用...

JSはアニメーションのレイアウト変換を実装します

JS でアニメーションを記述する場合、移動前に相対位置を絶対位置に変換してからアニメーション機能を実...