自定义指令限制数字的输入范围以及允许的小数位数

新建limitNumber.js文件

// limitNumber.js
/*
* 自定义指令限制数字的输入范围以及允许的小数位数
* 如果最后的输入结果为 - 或者 . 在回车或者失焦后会变成 ''
* 当输入 -.5 或者 .5 的时候会自动补充0 变成 -0.5 或者 0.5
* 允许输入中文 。 会自动变成 . 
* 如果以 . 结尾,比如 5. 会自动变成 5
* 如果中间出现 - 号如何处理,有两种处理,只需打开相应的注释即可
* 1. 如果输入4-5 则不允许输入- 变成45
* 2. 如果输入 4-5 自动变成 -45
* 最后输入框的绑定值类型是 string 类型
* v-limit-number="{ 
    min: -100, 限制输入的最小值
    max: 100, 限制输入的最大值
    decimal:3 限制输入的小数点几位
  }"
*/
export default (app) => {
  app.directive('limitNumber', {
    mounted(el, binding) {
      const decimal= binding.value.decimal || 0;
      const min= binding.value.min||0
      el.handlerInput = function (event) {
        let input = event.target;
        let value = input.value;
        let oldValue = input.value;
  
        // 移除非数字、负号、小数点的字符
        value = value.replace(/[^-\d.。]/g, '')
        // 连续的两个 - 换成一个 -
        .replace(/-{2,}/g, '-')
        // 处理负号位置,确保只有一个负号
          .replace(/(\d+)?-+(\d+)?/, (_, num1, num2) => { // 当有 - 符号出现时候
          if (num1 === undefined) {
            return '-'+(num2||'');
          } else {
          //  return (num1||'') + (num2||''); // 如果输入4-5 则不允许输入- 变成45
            return '-'+(num1||'') + (num2||''); // 如果输入 4-5 自动变成 -45
          }
        })
        .replace(//g, '.') //  将中文。转换为.
        .replace(/\.{2,}/g, '.')  // 连续的两个 . 换成一个 .
        .replace('.', '$#$')
        .replace(/\./g, '')
        .replace('$#$', '.')   // 只允许出现一次 .
        .replace('-', '$#$')
        .replace(/-/g, '')
        .replace('$#$', '-'); // 只允许出现一次 -
  
        value = value.replace(/(?<=^-?)(\.\d+)|[^-\d.]/g, match => {
          // 如果匹配到的是小数点和数字,且小数点后只有一个数字,补充零
          if (match.startsWith('.') && match.length === 2) {
            return '0' + match;
          }
          return match;
        });
  
        // 处理小数点的位置,确保只有一个小数点且小数位数不超过指定值
        let decimalIndex = value.indexOf('.');
        if (decimalIndex > -1) {
          if(decimal){
            let decimalPart = value.substring(decimalIndex + 1);
            if (decimalPart.length > decimal) {
              decimalPart = decimalPart.substring(0, decimal);
              value = value.substring(0, decimalIndex + 1) + decimalPart;
            }
          }else{
            value = value.substring(0, decimalIndex);
          }
        }
  
        // 转换为数字之后不为NaN
        if(!isNaN(Number(value))){
          if (+value > binding.value.max || +value < min) {
            // 处理最大值和最小值
            value = Math.min(Math.max(value, min), binding.value.max);
          }
        }
  
        // 判断是否需要更新,避免进入死循环
        if (oldValue.toString() !== value.toString()) {
          input.value = value;
          //  手动触发 input 事件以确保数据和视图同步 不然会出现当页面为55,且最大值为100的时候,再输入一个5,页面会呈现100,但是实际值为555,会页面与值不同步
          input.dispatchEvent(new Event('input'));
        }
      };
      el.handlerChange= function (event){
        let input = event.target;
        let value = input.value;
        let oldValue = input.value;
        // 当输入框失去焦点或者回车的时候,如果不能转换成数字类型,则置为空 比如 - . -.
        if(isNaN(Number(value))){
          value=''
        }
        value=value.replace(/\.$/g, '') // 以小数点结尾将小数点置为空
        value=value===''?'':Number(value)
         // 判断是否需要更新,避免进入死循环
         input.value = value;
         if (oldValue.toString() !== value.toString()) {
          //  手动触发 input 事件以确保数据和视图同步 不然会出现当页面为'',实际值为 -
          input.dispatchEvent(new Event('input'));
        }
      }
  
      el.addEventListener('input', el.handlerInput);
      el.addEventListener('change', el.handlerChange);
    },
    unmounted(el) {
      el.removeEventListener('input', el.handlerInput);
      el.removeEventListener('change', el.handlerChange);
    }
  })
}



在main.js中注册

import limitNumberfrom  '@/directive/limitNumber.js'
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.use(limitNumber)

使用

<template>
  <div>
    <el-input class="width-120" v-limitNumber="{  max: 100}" v-model="intNum" placeholder="正整数" />
    <el-input class="width-120" v-limit-number="{ min: -100, max: 100 }" v-model="positiveNum" placeholder="数数" />
    <el-input class="width-120" v-limit-number="{ min: -100, max: 100, decimal: 1 }" v-model="onePointNum" placeholder="一位小数" />
    <el-input class="width-120" v-limit-number="{ min: -100, max: 100, decimal: 6 }" v-model="twoPointNum" placeholder="两位小数" />
  </div>
</template>
<script setup>
import { onMounted,ref } from 'vue';

const intNum=ref('')
const positiveNum=ref('')
const onePointNum=ref('')
const twoPointNum=ref('')

onMounted(() => {
  
});
</script>
<style lang="less" scoped>
  .width-120{
    display: block;
    width: 120px;
  }
</style>

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值