Vue input 控件: 通過自定義指令(directive)使用正則表達式限制input控件的輸入


 前言:

網站中的input輸入框使用非常廣泛,因業務場景不同需要對輸入框做合法性校驗或限制輸入,比如電話號碼、郵件、區號、身份證號等。input框的不合法內容主要有兩種方式處理:1.用戶輸入內容后,通過規則驗證告知用戶不合法,2.禁止輸入不符合規則字符。下面基於第2種情況,針對Vue中的input控件通過自定義指令(directive),使用正則表達式限制input控件的輸入。

工作流程:

input控件綁定v-model ---> 通過自定義指令(v-restrict)設定驗證的正則表達式 ---> 監控控件的keyup、keydown、paste事件,驗證字符合法性 ---> 替換非法字符 ---> 替換后的結果更新綁定到v-model的變量里

控件元素代碼:

<v-text-field label="Test"
      v-model="testtext"
      v-restrict="/[^a-zA-Z0-9]/g"
</v-text-field>

自定義指令(directive)代碼:

import Vue from "vue";

Vue.directive("restrict", {
  bind(el, binding) {
    const target =
      el instanceof HTMLInputElement ? el : el.querySelector("input");
    target.addEventListener("keydown", e => {
      if (binding.value) {
        // Regex check
        if (binding.value.test(e.target.value)) {
          e.target.value = e.target.value.replace(binding.value, "");
 e.target.dispatchEvent(new Event("input"));//調用input事件使vue v-model綁定更新,下面相同         }
      }
    });
    target.addEventListener("paste", e => {
      if (binding.value) {
        // Regex check
        if (binding.value.test(e.target.value)) {
          e.target.value = e.target.value.replace(binding.value, "");
          e.target.dispatchEvent(new Event("input"));
        }
      }
    });
    target.addEventListener("keyup", e => {
      if (binding.value) {
        // Regex check
        if (binding.value.test(e.target.value)) {
          e.target.value = e.target.value.replace(binding.value, "");
          e.target.dispatchEvent(new Event("input"));
        }
      }
    });
  } // end bind
}); // end directive

v-model本質及實現原理

通過下面兩行代碼給input輸入框綁定值並添加事件鈎子:

這實際上就是 input 實現 v-model 的精髓,通過修改 AST 元素,給 el 添加一個 prop,相當於我們 在 input 上動態綁定了 value又給 el 添加了事件處理,相當於 在 input 上綁定了 input 事件,其實轉換成模板如下:

其實就是動態綁定了 input 的 value 指向了 messgae 變量,並且在觸發 input 事件的時候去動態把 message 設置為目標值,這樣實際上就完成了數據雙向綁定了,所以說 v-model 實際上就是語法糖。

通過下面的window.getEventListeners(obj)就能看出在這個控件上綁定了input方法,當通過監聽事件修改e.target.value時,並未調用input方法,所以v-model的值沒有變化,需要通過代碼(e.target.dispatchEvent(new Event("input"));)手動觸發input事件。
 
下面代碼可以驗證e.target.value變化與v-model的聯動變化過程:
Vue template code:
<v-text-field label="Test"
      v-model="testtext"
      @keyup="testkeyup($event)">
      <v-icon medium
        slot="append"
        @click.native="test()">save</v-icon>
</v-text-field>

Vue script code:
 data{testtext: "zsl"}
 methods: {
    test() {
      this.testtext += "a";
    },
    testkeyup(e) {
      e.target.value += "b";
      var eventb = new Event("input");
      e.target.dispatchEvent(eventb);
      console.log(
        "e.target.value: " +
          e.target.value +
          " | this.testtext: " +
          this.testtext
      );
    }
}
View Code

 

獲取某元素綁定的所有事件(Listener)

通過Chrome中,在Console窗口里,通過window.getEventListeners(obj)獲取某個元素綁定的所有事件(listener)

 

e.target.value的修改(change)不會自動調用vue的input方法,通過dispatchEvent的方式手動調用

e.target.dispatchEvent(new Event("input"));

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM