Vue で変数式セレクターを実装する方法

Vue で変数式セレクターを実装する方法

入力ボックスに式を入力することは、ミドルオフィス プロジェクトでは一般的なシナリオです。通常、特定の文字 ($ など) を入力すると、ドロップダウン リストが表示されます。ユーザーはドロップダウン リスト内の変数をクリックし、入力ボックスに他の演算子を入力し続けて式を作成します。効果は次のようになります。

前回のプロジェクトでは、React + TypeScrpt を使用して、React 版の変数式セレクターを実装しました。この記事では、Vue を使用して変数式セレクターを実装する方法を紹介します。

この変数式により、次の効果が得られます。

  1. 入力ボックスに特定の文字を入力すると、ドロップダウン リストが表示されます。
  2. キーボードの上下キーを押すことでドロップダウン オプションを切り替えることができます。ドロップダウン オプションをマウスでクリックするか、Enter キーを押すと、選択した内容が入力ボックスに表示されます。
  3. 入力文字の任意の位置にカーソルを移動し、ドロップダウン リストでコンテンツを選択すると、選択したコンテンツが現在のカーソル位置に表示されます。
  4. ドロップダウン リストが表示されているが、コンテンツが選択されていない場合、入力ボックスは入力禁止になります。コンテンツが選択された後、入力ボックスは引き続きコンテンツを入力できるようになります。
  5. 入力ボックスの履歴の表示を無効にします。

HTML構造の定義

既存のセレクターでは必要な効果が得られないため、セレクターを独自に実装する必要があります。 input タグを選択セレクターの入力ボックスとして使用し、ul li タグを選択セレクターのドロップダウン リストとして使用します。基本的な HTML 構造は次のとおりです。

<div class="式コンテナ">
 <入力 />
 <div v-if="表示可能" クラス="式リストボックス">
 <ul class="式UlBox">
  <li></li>
 </ul>
 </div>
</div>

入力タグバインディング属性

Vue では、要素またはサブコンポーネントの参照情報を登録する場合は、ref 属性を追加する必要があります。 ref を使用して登録された参照情報は、親コンポーネントの refs オブジェクトに登録されます。操作が必要な要素またはサブコンポーネントは、refs オブジェクトを通じて見つけることができます。そのため、input タグに ref 属性を追加します。

<input ref="inputRef" />

入力タグに ref 属性を追加するだけでなく、入力タグにイベントをバインドする必要もあります。 Vue では、通常、イベントをバインドするために v-on (略語: @) を使用します。 blur、keydown、input イベントを input タグにバインドします。

<入力
 ref="入力参照"
 v-model="expressValue"
 クラス="ant-input"
 :readOnly="読み取り専用 ? true : false"
 オートコンプリート="オフ"
 :placeholder="プレースホルダー"
 @blur="inputOnBlurHandle"
 @keydown="inputOnKeyDownHandle"
 @change="onchangeHandle"
 @input="onInputHandle"
/>

入力タグはキーダウンイベントをリッスンします

keydown イベントを input タグにバインドし、このときに押されたキーボードのキーをリッスンします。shift + $ を同時に押すと、ドロップダウン リストが表示され、入力ボックスの現在の値が保存され、input タグは編集不可に設定され、ドロップダウン リストからコンテンツのみを選択できるようになります。 keydown にバインドされたイベント処理関数は次のとおりです。

// 入力ボックスのキーダウンイベント inputOnKeyDownHandle(e) {
 // Shift + $ キーを同時に押す if (e.keyCode === 52 && e.shiftKey) {
 // 入力ボックスの値を取得します。const expressValue = e.target.value;
 this.setInputValue(expressValue);

 // 現在のカーソル位置を取得します。const position = getPositionForInput(this.$refs.inputRef);
 // 現在のカーソルの開始位置 const cursorIndex = position.start;

 // カーソルの位置を入力の範囲プロパティに設定します // updateRange(this.$refs.inputRef);

 // カーソルの開始位置を保存します。this.saveCursorIndex({ start: cursorIndex });
 // ドロップダウン選択ボックスを表示するように設定します。this.setSelectedBoxVisible(true);
 // 入力タグを編集不可に設定し、ドロップダウン リストからの選択のみを許可します。this.setInputIsReadonly(true);
 }
},

li タグバインディング属性

選択セレクターは、ul li タグを使用して実装されます。ドロップダウン オプションを選択する場合は、li タグを操作する必要があるため、li タグに ref 属性とクリックおよびキーダウン イベントを追加し、HTML5 の data-* 属性を使用してオプション値を保存する必要があります。

<ul ref="ulRef" class="expressionUlBox">
 <li
 v-for="(item, index) オプション内"
 ref="liRef"
 :key="アイテム.フィールド"
 :data-set="アイテム"
 :data-index="インデックス"
 :data-value="アイテムフィールド"
 タブインデックス="0"
 @click="liClickHandle"
 @keydown="liKeyDownHandle"
 >
 {{アイテム名}}
 </li>
</ul>

liタグがフォーカスされる

通常の div/span/li およびその他の要素ノードは、直接フォーカスを取得できません。 div/span/li などの要素ノードの onfocus イベントと onblur イベントをトリガーする必要がある場合は、それらに tabindex 属性を追加する必要があります。 tabindex 属性は、実際には、コンピュータ上で「Tab」ボタンがクリックされたときにカーソルが移動する位置を指定します。コンピュータ上で「Tab」ボタンがクリックされたとき、tabindex 属性の値が小さいほど (最小値は 0)、タブがフォーカスを取得するまでの時間が短くなります。

実装した選択セレクターでは、オプション値を切り替えるためにキーボードの上下キーを使用する必要があるため、li が onfocus イベントと onblur イベントをトリガーできるように、 li タグに tabindex 属性を追加する必要があります。

<li tabindex="0"></li>

グローバルキーボードイベントリスナー

キーボード イベントをグローバルに監視するということは、実際にはイベントをドキュメントにバインドすることを意味します。作成されたライフサイクル フックでキーボード イベントをリッスンします。現在押されているキーが上キーまたは下キーの場合、ドロップダウン オプションは上キーまたは下キーを使用して切り替えることができます。

作成された() {
 _this は定数です。
 document.onkeydown = 関数(){
 定数キー = window.event.keyCode;
 // 上下キーif (key === 38 || key === 40) {
  _this.upAndDownKeySwitch(キー);
 }
 //左と右のキー else if (key === 39 || key === 37) {
  // _this.leftAndRightKeySwitch(キー);
 }
 };
},

キーボードの上下キーを使用してセレクター ドロップダウン オプションを切り替える処理ロジックは次のとおりです。

// キーボードの上下キー選択式 upAndDownKeySwitch(key) {
 liNodes を this.$refs.liRef に設定します。
 liNodes の長さを定数で指定します。

 // Dw 矢印キー if (liNodes && liLength && key === 40) {
 定数カウント =
  this.arrowCount.dwArrow === liLength - 1
  ? 0
  : this.arrowCount.dwArrow + 1;
 // フォーカスを取得したときに最初の li が表示領域に表示されない問題を解決するためにパディングを設定します if (liLength > 1) {
  (カウント === 0)の場合{
  this.$refs.ulRef.style.padding = "40px 0 10px 0";
  } それ以外 {
  this.$refs.ulRef.style.padding = "10px 0";
  }
 }
 
 // 現在のli要素がフォーカスを取得します liLength && liNodes[count].focus();
 // 現在フォーカスされている li 要素が可視領域に表示されるように ul の scrollTop を設定します if (count === liLength - 1) {
  // 最後の li 要素が表示領域に表示できない問題を解決します this.$refs.ulRef.scrollTop = count * 40;
 } それ以外 {
  this.$refs.ulRef.scrollTop = count * 10;
 }

 // カウントステータスをコンポーネントのコンテンツ状態に保存します。this.arrowCount = { upArrow: count, dwArrow: count };
 }

 // 上矢印キー if (liNodes && liLength && key === 38) {
 定数カウント =
  this.arrowCount.upArrow <= 0
  ?li長さ - 1
  : this.arrowCount.upArrow - 1;
 // フォーカスを取得したときに最初の li が表示領域に表示されない問題を解決するためにパディングを設定します if (liLength > 1) {
  if (count === liLength - 1) {
  this.$refs.ulRef.style.padding = "10px 0 40px 0";
  } それ以外 {
  this.$refs.ulRef.style.padding = "10px 0";
  }
 }
 // 現在のli要素がフォーカスを取得します liNodes[count].focus();
 // ul の scrollTop を設定して、現在フォーカスされている li 要素が表示領域に表示されるようにします。this.$refs.ulRef.scrollTop = count * 60;
 // カウントステータスをコンポーネントのコンテンツ状態に保存します。this.arrowCount = { upArrow: count, dwArrow: count };
 }
},

入力タグの値を設定する

デフォルトでは、入力した文字の任意の位置にカーソルを移動し、ドロップダウン オプションを選択すると、入力した文字の末尾にオプション値が挿入されます。現在のカーソル位置にオプション値を挿入したいので、カーソル位置を計算し、正しい位置にオプション値を追加する必要があります。これには、カーソルの位置とテキストの選択に関する関連知識が必要です。詳細については、「選択」を参照してください。

/**
 * テキストを挿入 * @param ctrl 入力要素オブジェクト (input、textarea など)
 * @param inputValue 入力ボックスの値*/
エクスポート関数 insertAtCursor(ctrl, inputValue) {
 // IE サポート
 if (ドキュメント選択) {
 Ctrl+Focus();
 // ドキュメント.選択.作成範囲() 
 // 現在のテキスト選択に基づいて TextRange オブジェクトを返すか、コントロール選択に基づいて ControlRange オブジェクトを返します。const sel = document.selection.createRange();
 // 現在の TextRange オブジェクトにテキストを設定します。sel.text = inputValue;
 } そうでない場合 (ctrl.selectionStart || ctrl.selectionStart === 0) {
 // selectionStart テキスト選択領域の開始位置 // selectionEnd テキスト選択領域の終了位置 // MOZILLA など
 定数開始位置 = ctrl.selectionStart;
 定数 endPos = ctrl.selectionEnd;
 // カーソル位置に値を挿入 ctrl.value =
  // カーソル位置の前の値 ctrl.value.substring(0, startPos) +
  //挿入する値 inputValue +
  //カーソル位置の後の値 ctrl.value.substring(endPos, ctrl.value.length);
 // カーソルの位置をリセットします // 値を挿入した後、カーソルの位置は文字列の末尾にある必要があります // ページ上の点滅するカーソルは、実際には幅 0 の特別な選択範囲です。簡単に言えば、選択範囲の左と右の境界が交差してカーソルを形成します ctrl.selectionStart = startPos + inputValue.length;
 ctrl.selectionEnd = 開始位置 + 入力値の長さ;
 } それ以外 {
 ctrl.value += 入力値;
 }
 // 入力要素オブジェクト (input、textarea) がフォーカスを取り戻します。このとき、カーソルの位置は入力文字の末尾にあるはずです。ctrl.focus();
}

フルエフェクトプレビュー

以上が、Vue が変数式セレクターを実装する方法の詳細です。Vue の変数式セレクターの実装の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Vue 日付時刻ピッカーコンポーネントの使い方の詳細な説明
  • Cascaderカスケードセレクタデータエコーを使用したVueの落とし穴についての簡単な説明
  • Vueはマルチラベルセレクタを実装する
  • Vant で時間セレクターを実装するための Vue サンプル コード
  • mpvue WeChat アプレットの複数列セレクターの使用により、州と都市の選択を実現
  • Vueアイコンセレクターのサンプルコード

<<:  Mysql が CPU を過剰に占有する場合の最適化方法 (必読)

>>:  Docker チュートリアル: コンテナの使用 (簡単な例)

推薦する

Vueでキャッシュされたページを管理する方法

目次問題1: 破壊1. 破壊する方法2. いつ破壊するか2.1 解決策1: route.queryを...

JavaScript の 3 つの BOM オブジェクト

目次1. 場所オブジェクト1. URL 2. 場所オブジェクトのプロパティ3. ロケーションオブジェ...

Linuxでホスト名を永続的に変更する方法

ホスト名を変更する場合は、以下の手順に従ってください。ホスト名の使用hostnameコマンドを使用す...

MySql SQL最適化のヒントの共有

ある日、内部結合を含む SQL ステートメントの実行速度はそれほど遅くはない (0.1 ~ 0.2)...

Docker、Nginx、Jenkins をベースにした自動フロントエンド デプロイメント

目次事前準備展開ターゲットDocker環境構築クラウドサーバーに接続Docker環境をインストールす...

Nginx ロケーション設定のチュートリアル (ゼロから)

基礎位置の一致順序は、「最初に正規表現に一致し、次に共通表現に一致」です。実際のロケーションの一致順...

Mac VMware Fusion CentOS7 静的 IP 構成チュートリアル図

目次CentOS7をインストールする静的IPの設定viを使用してファイルを編集するCentOS7をイ...

MySQL グループレプリケーションの設定手順 (推奨)

MySQL-Group-Replication は、MySQL-5.7.17 で開発された新しい機...

CSSアニメーションを使用して背景のシームレスな無限ループを実装する例

1. 需要絵が左から右へ無限ループで動く2. コードモバイルデバイスに適用されているため、rem 単...

HTML入力ファイルコントロールはアップロードされるファイルの種類を制限します

入力ファイルの HTML コントロールを Web ページに追加します。 <input id=&...

Linux システム Docker への ASP.NET Core アプリケーションのデプロイのプロセス分析

目次1. システム環境2. 運用プロセスと途中で遭遇した問題1. システム環境1. Tencent ...

Node.js でメモリ効率の高いアプリケーションを作成する方法

目次序文問題: 大きなファイルのコピーNodeJS のストリームとバッファバッファストリーム解決策 ...

Linux 3.X/4.x/5.x でパゴダ パネルのパスワードを忘れた場合の解決方法

ssh に入り、次のコマンドを入力してパスワードをリセットします (コマンドの末尾の「testpas...

表 td 画像水平および垂直中央揃えコード

HTMLコード:コードをコピーコードは次のとおりです。 <td align="cen...

MySQLプロセス関数の一般的な使用例の分析

この記事では、例を使用して MySQL プロセス関数の一般的な使用方法を説明します。ご参考までに、詳...