vue自定义指令——input输入类型限制(数字、浮点、整数、英文等),解决中文输入法双向绑定失效问题

版本更新

2023.3.23——修复浮点型输入0问题

前言

实现一个vue自定义指令——输入框(input,el-input)输入内容类型限制,解决中文输入法双向绑定失效问题,多种类型支持,数字类型,浮点类型、英文类型、整数类型、四则运算等

一、基本步骤

以element,el-input组件为例:
1.在自定义指钩子函数bind或inserted通过querySelector找到输入框(input标签)dom对象
2.监听input的onkeyup事件,获取输入值,校验并替换输入值,限制输入类型,重新给输入框设值
3.通过compositionstart和compositionend事件设置锁定标识,解决中文输入法双向绑定失效问题

二、代码实现

1.input.js

代码如下:

export default {
  bind(el, binding, vnode) {
    const input = el.querySelector('.el-input__inner') || el.querySelector('.el-textarea__inner') || el;
    input.addEventListener('compositionstart', () => {
      vnode.locking = true//解决中文输入双向绑定失效
    })
    input.addEventListener('compositionend', () => {
      vnode.locking = false//解决中文输入双向绑定失效
      input.dispatchEvent(new Event('input'))
    })
    //输入监听处理
    input.onkeyup = () => {
      if (vnode.locking) {
        return;
      }
      // v-input.num
      if (binding.modifiers.num) {//只能输入数字(开头可以多个0)
        onlyNum(input);

      }
      //v-input.num_point
      else if (binding.modifiers.num_point) {//只能输入数字+小数点(可以多个小数点)
        onlyNumPoint(input)
      }
      //v-input.float
      else if (binding.modifiers.float) {//只能输入浮点型(只能一个小数点)
        onlyFloat(input, binding.value)
      }
      //  v-input.int
      else if (binding.modifiers.int) {//只能输入整数(0+正整数)(开头不能多个0)
        onlyInt(input)
      }
      //v-input.intp
      else if (binding.modifiers.intp) {//只能输入正整数
        onlyIntp(input)
      }
      //v-input.alp
      else if (binding.modifiers.alp) {//只能输入字母
        onlyAlp(input)
      }
      //v-input.num_alp
      else if (binding.modifiers.num_alp) {//只能输入数字+字母
        onlyNumAlp(input)
      }
      //v-input.arith
      else if (binding.modifiers.arith) {//四则运算符+数字
        onlyArith(input)
      }
      input.dispatchEvent(new Event("input"));
    }

    //数字
    function onlyNum(input) {
      input.value = input.value.replace(/\D+/g, '');
    }
    //整数(0+正整数)
    function onlyInt(input) {
      let value = input.value;
      value = value.replace(/\D+/g, '');
      input.value = value ? Number(value).toString() : value//去掉开头多个0
    }
    //正整数
    function onlyIntp(input) {
      if (!/^[1-9][0-9]*$/.test(input.value)) {
        let value = input.value.replace(/\D+/g, '');
        if (value && value.substring(0, 1) === '0') {//0开头去除0
          value = value.substring(1)
        }

        input.value = value
      }
    }

    //数字+小数点
    function onlyNumPoint(input) {
      input.value = input.value.replace(/[^\d.]/g, "");
    }

    //浮点型
    // eslint-disable-next-line no-unused-vars
    function onlyFloat(input, n) {
      let value = input.value;
      value = value.replace(/[^\d.]/g, '');
      value = value.replace(/^\./g, '');
      value = value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
      if (n&&Number(n)>0) {//限制n位
        var d = new Array(Number(n)).fill(`\\d`).join('');
        // eslint-disable-next-line no-useless-escape
        var reg = new RegExp(`^(\\-)*(\\d+)\\.(${d}).*$`, 'ig');
        value = value.replace(reg, '$1$2.$3')
      }
      if (value && !value.includes('.')) {
           value =  Number(value).toString()//去掉开头多个0
      }
      input.value = value
    }
    //字母
    function onlyAlp(input) {
      input.value = input.value.replace(/[^A-Za-z]/g, '');
    }
    //数字+字母
    function onlyNumAlp(input) {
      input.value = input.value.replace(/[^A-Za-z0-9]/g, '');
    }

    //四则运算+-*/()数字
    function onlyArith(input) {
      let value = input.value
      if (value) {
        input.value = value.split('').reduce((prev, cur) => {
          // eslint-disable-next-line no-useless-escape
          if (/^[\d|\-|\+|\*|\/|\.|\(|\)]+$/.test(cur)) {
            return prev + cur
          }
          return prev
        }, '')
      }
    }

  },

}






2.install.js(注册文件)

代码如下:

import input from "./input.js";

export default{
    install:Vue=>{
        Vue.directive('input',input)
    }
}

3.全局注册

main.js

 import inputDirective from './directive/input/install';
 Vue.use( inputDirective );

4.页面调用

         <!-- 只能数字 -->
        <el-input v-input.num v-model="input"></el-input>
         <!-- 只能数字+小数点 -->
        <el-input v-input.num_point v-model="input"></el-input>
         <!-- 只能整数 -->
        <el-input v-input.int v-model="input"></el-input>
         <!-- 浮点型后面限制2位 -->
        <el-input v-input.float="2" v-model="input"></el-input>
         <!-- 只能英文 -->
        <el-input v-input.alp v-model="input"></el-input>

三、使用说明

指令               说明                                                   值
v-input.num              只能输入数字(开头可以多个零)                                             无
v-input.num_point    只能输入数字+小数点(可以多个小数点,开头可以多个零)    无
v-input.int                 只能输入整数(0+正整数)(开头不能多个0)                        无
v-input.intp               只能输入正整数                                                                        无
v-input.float             只能输入浮点型                                n:限制输入小数点后n位,默认不限制
v-input.alp               只能输入字母                                                                        无
v-input.num_alp     只能输入数字+字母                                                                    无
v-input.arith            四则运算符+数字                                                                         无
 

可以按需在扩展类型限制指令

四、npm安装指令插件

npm install vue-el-input-directive

main.js

import  inputDirective from 'vue-el-input-directive'
Vue.use(inputDirective)

以上参考vue自定义指令——input输入类型限制(数字、浮点、整数、英文等),解决中文输入法双向绑定失效问题_vue 中文输入法_pixle0的博客-CSDN博客

方法:

import inputValidate from '@/utils/inputValidate.js'
inputValidate.js
import Vue from 'vue'
// 针对 el-input做的限制,只能输入正整数
const input = Vue.directive('input', {
    bind(el, binding, vnode) {
        const input = el.querySelector('.el-input__inner') || el.querySelector('.el-textarea__inner') || el;
        input.addEventListener('compositionstart', () => {
            vnode.locking = true//解决中文输入双向绑定失效
        })
        input.addEventListener('compositionend', () => {
            vnode.locking = false//解决中文输入双向绑定失效
            input.dispatchEvent(new Event('input'))
        })
        //输入监听处理
        input.onkeyup = () => {
            if (vnode.locking) {
                return;
            }
            // v-input.num
            if (binding.modifiers.num) {//只能输入数字(开头可以多个0)
                onlyNum(input);
            }
            //v-input.num_point
            else if (binding.modifiers.num_point) {//只能输入数字+小数点(可以多个小数点)
                onlyNumPoint(input)
            }
            //v-input.float
            else if (binding.modifiers.float) {//只能输入浮点型(只能一个小数点)
                onlyFloat(input, binding.value)
            }
            //  v-input.int
            else if (binding.modifiers.int) {//只能输入整数(0+正整数)(开头不能多个0)
                onlyInt(input)
            }
            //v-input.intp
            else if (binding.modifiers.intp) {//只能输入正整数
                onlyIntp(input)
            }
            //v-input.alp
            else if (binding.modifiers.alp) {//只能输入字母
                onlyAlp(input)
            }
            //v-input.num_alp
            else if (binding.modifiers.num_alp) {//只能输入数字+字母
                onlyNumAlp(input)
            }
            //v-input.arith
            else if (binding.modifiers.arith) {//四则运算符+数字
                onlyArith(input)
            }
            input.dispatchEvent(new Event("input"));
        }

        //数字
        function onlyNum(input) {
            input.value = input.value.replace(/\D+/g, '');
        }
        //整数(0+正整数)
        function onlyInt(input) {
            let value = input.value;
            value = value.replace(/\D+/g, '');
            input.value = value ? Number(value).toString() : value//去掉开头多个0
        }
        //正整数
        function onlyIntp(input) {
            if (!/^[1-9][0-9]*$/.test(input.value)) {
                let value = input.value.replace(/\D+/g, '');
                if (value && value.substring(0, 1) === '0') {//0开头去除0
                    value = value.substring(1)
                }

                input.value = value
            }
        }

        //数字+小数点
        function onlyNumPoint(input) {
            input.value = input.value.replace(/[^\d.]/g, "");
        }

        //浮点型
        // eslint-disable-next-line no-unused-vars
        function onlyFloat(input, n) {
            let value = input.value;
            value = value.replace(/[^\d.]/g, '');
            value = value.replace(/^\./g, '');
            value = value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
            if (n&&Number(n)>0) {//限制n位
                var d = new Array(Number(n)).fill(`\\d`).join('');
                // eslint-disable-next-line no-useless-escape
                var reg = new RegExp(`^(\\-)*(\\d+)\\.(${d}).*$`, 'ig');
                value = value.replace(reg, '$1$2.$3')
            }
            if (value && !value.includes('.')) {
                value =  Number(value).toString()//去掉开头多个0
            }
            input.value = value
        }
        //字母
        function onlyAlp(input) {
            input.value = input.value.replace(/[^A-Za-z]/g, '');
        }
        //数字+字母
        function onlyNumAlp(input) {
            input.value = input.value.replace(/[^A-Za-z0-9]/g, '');
        }

        //四则运算+-*/()数字
        function onlyArith(input) {
            let value = input.value
            if (value) {
                input.value = value.split('').reduce((prev, cur) => {
                    // eslint-disable-next-line no-useless-escape
                    if (/^[\d|\-|\+|\*|\/|\.|\(|\)]+$/.test(cur)) {
                        return prev + cur
                    }
                    return prev
                }, '')
            }
        }

    },
})
export {input}
// v-input.num	只能输入数字(开头可以多个零)	无
// v-input.num_point	只能输入数字+小数点(可以多个小数点,开头可以多个零)	无
// v-input.int	只能输入整数(0+正整数)(开头不能多个0)	无
// v-input.intp	只能输入正整数	无
// v-input.float	只能输入浮点型	n:限制输入小数点后n位,默认不限制
// v-input.alp	只能输入字母	无
// v-input.num_alp	只能输入数字+字母	无
// v-input.arith	四则运算符+数字	无

使用:

 <el-input v-model.trim="ruleForm.abc"  v-input.num_point ></el-input>

7、自定义正则

11位数字
....

//v-input.phone
 else if (binding.modifiers.phone) {//手机 11位数字
      onlyPhone(input)
  }
 input.dispatchEvent(new Event("input"));


//11位数字
function onlyPhone(input) {
    let value = input.value;
     value = value.replace(/\D+/g, '');
     input.value = value ? Number(value.substring(0, 11)) : value
 }

vue 自定义指令 directive  vue 自定义指令 directive_qq_489366879的博客-CSDN博客

vue自定义指令_binding.modifiers_龙易安的博客-CSDN博客

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值