In the development process, the basic have encountered the need to limit the input of the situation, such as amount, only alphanumeric, can enter decimal, etc., online search for many methods also encountered some pits, so share out

1. Use modifiers to implement numeric input

In VUE, modifiers can be added after V-modal to restrict input, such as:

<input v-model.number="testValue" type="number">
Copy the code

.number can be implemented to limit the number input, but there are the following problems:

  • The type=”number” style will appear, which can be cleared by adding the following CSS
/* Normal Internet Explorer style clear */input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{
-webkit-appearance: none ! important;}
/* Firefox style clear */input[type="number"] { -moz-appearance:textfield; } Copy the code
  • The special symbol +-. Can be entered indefinitely, causing the value testValue in data to be emptied

The modifiers here also do not allow for custom restricted input and do not satisfy the requirements

2. Listen for input box changes

Listen for updates through @input, the implementation can only enter numbers, and can customize the restricted input content

<input v-model="testValue" @input="testValue = testValue.replace(/[^\d]/g,'')">
Copy the code

This method can meet the requirements, but cannot be packaged for bulk use

3. Encapsulate global directives

Encapsulating input limits input instructions

//input.js

const addListener = function(el, type, fn) {
  el.addEventListener(type, fn, false)
}
 // Remove whitespaceconst spaceFilter = function(el) {  addListener(el, 'input', () = > { el.value = el.value.replace(/\s+/, ' ')  }) }  // Restrict input to integers and decimals (for price classes, up to two decimal digits)const priceFilter = function(el) {  addListener(el, 'input', () = > {el.value = (el.value.match(/^\d*(\.? } \ d {0, 2)/g) [0]) | | null if (isNaN(el.value)) {  el.value = ' '  }  }) }  // Limit alphanumeric input only (for waybill number)const integerLetterFilter = function(el) {  addListener(el, 'input', () = > { el.value = el.value.replace(/[\W]/g,' ')  el.dispatchEvent(new Event('input'))  }) }  export default {  bind(el, binding) {  if(el.tagName.toLowerCase() ! = ='input') {  el = el.getElementsByTagName('input') [0] }  spaceFilter(el)  switch (binding.arg) {  case 'price':  priceFilter(el)  break  case 'integerLetter':  integerLetterFilter(el)  break  default:  console.warn('Unknown instruction type',binding.arg)  break  }  } } Copy the code

Register global custom directives

//main.js

import inputFilter from '@/directives/InputFilter.js'

Vue.directive('inputFilter', inputFilter)
Copy the code

Use the V-input-filter directive

<input v-modal="testValue" v-input-filter:price>
Copy the code

A hidden bug with this encapsulation is that the input box in the view is correct when a character is entered outside the re limit in the command, but the testValue in the browser control bar Vue Devtools is the last character entered.

For example, if you enter ABC and 123ABC, the input field is 123, but the actual testValue is C and 123c.

The reason is that the value bound in vUE is assigned by listening for input. Directly modifying the value of the input box will not trigger the input event. You need to manually trigger the input event again through dispatchEvent. So modify the value by listening for keyUP events as follows:

//input.js

.../ / image stabilizationlet debounce = (fn, delay) => {
 var delay = delay || 300;  var timer;  return function() {  var th = this;  var args = arguments;  if (timer) {  clearTimeout(timer);  }  timer = setTimeout(function() {  timer = null;  fn.apply(th, args);  }, delay);  }; }  // Restrict input to integers and decimals (for price classes, up to two decimal digits)const priceFilter = function(el) {  addListener(el, 'keyup', debounce(() => {// Add anti-shake to add decimal pointel.value = (el.value.match(/^\d*(\.? } \ d {0, 2)/g) [0]) | | null if (isNaN(el.value)) {  el.value = ' '  } // Format the decimal point without entering a decimal place el.value = +el.value // Trigger the input event el.dispatchEvent(new Event('input'))  })) }  // Limit alphanumeric input only (for waybill number)const integerLetterFilter = function(el) {  addListener(el, 'keyup', () = > { el.value = el.value.replace(/[\W]/g,' ')  el.dispatchEvent(new Event('input'))  }) }  ...Copy the code

I hope to share it with you and learn a better way. If you have a better way, please tell me, thank you!