[转] Vue限制输入 - Input 用 @input="input($event)" 然后 input(ev) 过滤 ev.target.value 最后再同步本组件及emit父组件

[转] Vue限制输入 Input 用 @input="input($event)" 然后 input(ev) 过滤 ev.target.value 最后再同步本组件及emit父组件


原文地址:https://binaryify.github.io/2017/03/13/Vue限制输入/
Published Mar 13, 2017

另外这个作者还有一个 俄罗斯方块的项目 也不错~
https://binaryify.github.io/

众所周知,Vue 要限制输入还是比较麻烦的,如果使用双向绑定,在数据变化后再去做处理,输入内容会闪烁,体验并不是很好 想要输入不闪烁,就不能使用双向绑定了,那么有什么办法呢? 首先可以监听键盘输入事件,然后判断 event.target.value 的值,但是这也有个明显的缺点,那就是移动端不会触发 keyup/keypress/keydown 事件,所以比较好的方法就是监听 input 事件

虽然现在解决了输入限制,但是不能使用双向绑定也不是办法,如何使用双向绑定呢?

这个也不复杂,我们可以把这个输入限制封装成组件,然后给这个组件添加 v-model=”value” 属性,在组件内部声明 props:[‘value’],在限制输入的函数最后 emit 处理过后的值给父组件就完成了既能够输入限制,又支持双向绑定的组件了

示例代码:

<!-- parent.vue -->
<template>
  <div id="app">
    <common-input v-model="value" :fixed='fixed' :sum="sum"  ></common-input>
    
  </div>
</template>

<script>
import commonInput from './components/commonExchangeInput.vue'
export default {
  name: 'app',
  components: {
    commonInput
  },
  data() {
    return {
      value: 0,
      fixed: 5,
      sum: 500
    }
  }
}
</script>
<!-- child.vue -->
<template>
  <input type="text" @input="input($event)" :value="val">
</template>

<script>
export default {
  props: ['value', 'fixed', 'sum'],
  data() {
    return {
      val: ''
    }
  },
  methods: {
    input(ev) {
      ev.target.value = ev.target.value.replace(/^0*(0\.|[1-9])/, '$1') // 解决 粘贴不生效
      ev.target.value = ev.target.value.replace(/[^\d.]/g, '') // 清除“数字”和“.”以外的字符
      ev.target.value = ev.target.value.replace(/\.{2,}/g, '.') // 只保留第一个. 清除多余的
      ev.target.value = ev.target.value
        .replace('.', '$#$')
        .replace(/\./g, '')
        .replace('$#$', '.')
      // ev.target.value = ev.target.value.replace(/^(\-)*(\d+)\.(\d\d\d\d).*$/, '$1$2.$3'); // 只能输入4个小数,且小数点前必须有数字
      const length = this.fixed
      const reg2 = new RegExp('^(-)*(\\d*?)\\.(\\d{1,' + length + '}).*$')
      ev.target.value = ev.target.value.replace(reg2, '$1$2.$3') // 只能输入N个小数,小数点前面可以没有数字
      if (ev.target.value.indexOf('.') < 0 && ev.target.value != '') {
        // 如果没有小数点,首位不能为类似于 01、02的金额
        if (
          ev.target.value.substr(0, 1) == '0' &&
          ev.target.value.length == 2
        ) {
          ev.target.value = ev.target.value.substr(1, ev.target.value.length)
        }
      }
      if (ev.target.value.indexOf('.') === 0 && ev.target.value.length > 1) {
        // 如果第一个字符时“.”,那么当“.”后面有数字后,"."前面自动补零
        ev.target.value = 0 + ev.target.value
      }
      if (this.sum) {
        if (Number(ev.target.value) > Number(this.sum)) {
          ev.target.value = this.sum
        }
      }
      this.val = ev.target.value
      this.$emit('input', this.val)
    }
  }
}
</script>
posted @ 2024-03-28 10:01  彭成刚  阅读(84)  评论(0编辑  收藏  举报