Vueどのように変数表現を選択しますか?


input入力ボックスに表式を入力すると中台項目でよく見られるシーンです。通常は特定の文字を入力する場合、ドロップダウンリストが表示され、ユーザーポイントはドロップダウンリストの変数を選択して、input入力ボックスに他の演算子を入力し続け、その効果は次の図のようです。

前の項目では、React+Type Scaptを使ってReact版の変数式選択器を実現しました。ここでは、Vueを使ってどのように変数式選択器を実現するかを紹介します。
この変数式は以下の効果をもたらします。
  • 入力ボックスに特定の文字を入力すると、プルダウンリストが表示されます。
  • は、キーボードの上下ボタンを通じてドロップダウンオプションを切り替えたり、マウスがドロップダウンオプションをクリックしたり、イベントキーを押したりして、選択した内容を入力ボックスに表示します。
  • カーソルは入力した文字の任意の位置に移動し、ドロップダウンリストの内容を選択し、選択した内容は現在のカーソル位置に表示されます。
  • プルダウンリストが表示されているが、プルダウンリストの内容が選択されていない場合、input入力ボックスは入力禁止となり、選択された内容のみが入力ボックスに入力され続けることができます。
  • 入力ボックスの履歴の表示を禁止する。
  • HTML構造を定義する
    既存のセレクタは私たちが望む効果を実現できないので、自分でセレクトを実現する必要があります。inputタグを私たちのselectセレクタの入力枠として使用し、ul liタグをselectセレクタのプルダウンリストとします。その基本的なHTML構造は以下の通りである。
    
    <div class="expressionContainer">
     <input />
     <div v-if="visible" class="expressionListBox">
     <ul class="expressionUlBox">
      <li></li>
     </ul>
     </div>
    </div>
    
    inputラベルバインディング属性
    Vueでは、要素またはサブコンポーネントに参照情報を登録するには、ref属性を追加する必要があります。refで登録された参照情報は、親コンポーネントのrefsオブジェクトに登録され、refsオブジェクトを介して、動作する要素またはサブコンポーネントを見つけることができる。したがって、私たちはinputタグにref属性を追加します。
    
    <input ref="inputRef" />
    
    inputラベルにref属性を追加する以外に、inputラベルバインディングイベントが必要です。Vueでは、v-onバインディングイベントが一般的に使用される。私たちはinputラベルにblur、keydown、inputイベントをバインドします。
    
    <input
     ref="inputRef"
     v-model="expressValue"
     class="ant-input"
     :readOnly="readonly ? true : false"
     autoComplete="off"
     :placeholder="placeholder"
     @blur="inputOnBlurHandle"
     @keydown="inputOnKeyDownHandle"
     @change="onchangeHandle"
     @input="onInputHandle"
    />
    
    inputタグ盗聴keydownイベント
    inputラベルにkeydownイベントをバインドし、この時に押されたキーボードのキーを傍受し、同時にshift+$を押すと、プルダウンリストが表示され、input入力ボックスの現在の値を保存し、inputタグを編集不可に設定し、プルダウンリストから内容を選択するしかない。keydownバインディングのイベントハンドリング関数は以下の通りです。
    
    // Input     keydown   
    inputOnKeyDownHandle(e) {
     //      shift + $  
     if (e.keyCode === 52 && e.shiftKey) {
     //    input      
     const expressValue = e.target.value;
     this.setInputValue(expressValue);
    
     //          
     const position = getPositionForInput(this.$refs.inputRef);
     //          
     const cursorIndex = position.start;
    
     //            input   range    
     // updateRange(this.$refs.inputRef);
    
     //          
     this.saveCursorIndex({ start: cursorIndex });
     //            
     this.setSelectedBoxVisible(true);
     //    input       ,           
     this.setInputIsReadonly(true);
     }
    },
    
    ラベルバインディングのプロパティ
    セレクタは、ul liタグを使用して実装され、ドロップダウンオプションを選択すると、liタグを操作する必要があるので、liタグにref属性とclick、keydownイベントを追加し、HTML 5のdata-*属性を利用してオプション値を記憶する必要があります。
    
    <ul ref="ulRef" class="expressionUlBox">
     <li
     v-for="(item, index) in options"
     ref="liRef"
     :key="item.field"
     :data-set="item"
     :data-index="index"
     :data-value="item.field"
     tabindex="0"
     @click="liClickHandle"
     @keydown="liKeyDownHandle"
     >
     {{ item.name }}
     </li>
    </ul>
    
    liタグがフォーカスを取得します。
    通常のdiv/span/liなどの要素ノードに対して直接的に焦点を得ることはできない。div/span/liなどの要素ノードのonfocusイベントとonblurイベントをトリガする必要があるならば、tabindex属性を追加する必要がある。tabindex属性は実はコンピュータの「Tab」健をクリックする時にカーソルが移動する位置を指定しています。コンピュータの「Tab」健をクリックする時、tabindex属性値が小さい(最小は0)ほど、その位置のラベルが先にフォーカスを得ます。
    私達が実現したselectセレクタでは、キーボードの上下キーを使ってオプション値を切り替える必要があるので、liタグにtabindex属性を追加する必要があり、liがonfocusイベントとonblurイベントをトリガできるようにする。
    
    <li tabindex="0"></li>
    
    グローバルキーボードイベント
    キーボードイベントを大局的に傍聴するということは、事件をマルチタスクに結びつけるということです。私たちはcreatedライフサイクルフックの中でキーボードのイベントを監督します。現在押しているキーが上、下キーであれば、上、下キーでドロップダウンオプションを切り替えることができます。
    
    created() {
     const _this = this;
     document.onkeydown = function () {
     const key = window.event.keyCode;
     //  、  
     if (key === 38 || key === 40) {
      _this.upAndDownKeySwitch(key);
     }
     //  、  
     else if (key === 39 || key === 37) {
      // _this.leftAndRightKeySwitch(key);
     }
     };
    },
    
    キーボード上下キーでセレクタのドロップダウンオプションを切り替える処理ロジックは以下の通りです。
    
    //     、         
    upAndDownKeySwitch(key) {
     const liNodes = this.$refs.liRef;
     const liLength = liNodes.length;
    
     // Dw Arrow  
     if (liNodes && liLength && key === 40) {
     const count =
      this.arrowCount.dwArrow === liLength - 1
      ? 0
      : this.arrowCount.dwArrow + 1;
     //    padding,       li                  
     if (liLength > 1) {
      if (count === 0) {
      this.$refs.ulRef.style.padding = "40px 0 10px 0";
      } else {
      this.$refs.ulRef.style.padding = "10px 0";
      }
     }
     
     //    li       
     liLength && liNodes[count].focus();
     //    ul   scrollTop,         li          
     if (count === liLength - 1) {
      //        li               
      this.$refs.ulRef.scrollTop = count * 40;
     } else {
      this.$refs.ulRef.scrollTop = count * 10;
     }
    
     //    count            state  
     this.arrowCount = { upArrow: count, dwArrow: count };
     }
    
     // Up Arrow  
     if (liNodes && liLength && key === 38) {
     const count =
      this.arrowCount.upArrow <= 0
      ? liLength - 1
      : this.arrowCount.upArrow - 1;
     //    padding,       li                  
     if (liLength > 1) {
      if (count === liLength - 1) {
      this.$refs.ulRef.style.padding = "10px 0 40px 0";
      } else {
      this.$refs.ulRef.style.padding = "10px 0";
      }
     }
     //    li       
     liNodes[count].focus();
     //    ul   scrollTop,         li          
     this.$refs.ulRef.scrollTop = count * 60;
     //    count            state  
     this.arrowCount = { upArrow: count, dwArrow: count };
     }
    },
    
    inputラベルの値を設定します。
    デフォルトでは、入力した文字の任意の位置にカーソルを移動します。ドロップダウンオプションを選択すると、入力した文字の一番後ろにオプションの値が挿入されます。私たちが望む効果は、オプションの値が現在のカーソルの位置に挿入されます。したがって、カーソルがある位置を計算して、正しい位置にオプションの値を追加する必要があります。ここでは、カーソル位置およびテキスト選択領域に関する知識について、ステップセレクションによって深く知ることができる。
    
    /**
     *     
     * @param ctrl       (input、textarea  )
     * @param inputValue       value  
     */
    export function insertAtCursor(ctrl, inputValue) {
     // IE support
     if (document.selection) {
     ctrl.focus();
     // document.selection.createRange() 
     //            TextRange   ,          ControlRange   
     const sel = document.selection.createRange();
     //      TextRange       
     sel.text = inputValue;
     } else if (ctrl.selectionStart || ctrl.selectionStart === 0) {
     // selectionStart            
     // selectionEnd            
     // MOZILLA and others
     const startPos = ctrl.selectionStart;
     const 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 = startPos + inputValue.length;
     } else {
     ctrl.value += inputValue;
     }
     //       (input、textarea)      ,                  
     ctrl.focus();
    }
    
    効果のプレビュー
    以上がVueの変数式選択器の詳細な内容です。Vueに関する変数式選択器の詳細については、他の関連記事に注目してください。