【directives】自定义指令之input数值

2022-06-24  本文已影响0人  两年半练习程序员

需求

由于input输入框的number类型不调好用,故通过自定义指令给element el-input组件设置输入限制

功能

1.可设置允许输入的最大最小值
2.可设置精度
3.限制非数值输入

输入限制

1.小数点"."不允许出现在第一位,且只允许输入一次
2.负号"-"仅可以出现在第一位,且配置最小值允许出现负值时可用
3.限制输入法的输入事件

未实现功能TODO/(ㄒoㄒ)/~~

精度拦截目前在输入时未做拦截
原因:在输入框输入达到精度限制时,此时按ctrl+a想要执行覆盖选中重新输入操作时,输入事件会判断达到输入精度做大值,无法执行上述操作
替换方案:在输入框失去焦点时做精度格式化

有解决方案的小伙伴欢迎解答 😀T_T

demo如下👇

提供三个参数
{min: -100, max: 100, precision: 2},
1.min最小值:默认-100
2.max最小值:默认100
3.precision精度(保留小位数):默认2

'懒人'提醒

可根据需求修改默认值,或设置为null不做限制
只需将demo中对应的监听事件里 声明的 _min 和 _max 和 _precision 改为想要的默认值即可

//keypress下
let _precision = 2;
let _max = 100;
let _min = -100;
//keyup下
let _precision = 2;
let _max = 100;
let _min = -100;
//focusout
let _precision = 2;
<template>
  <div class="hello">
    <el-input
      type="text"
      v-model="test"
      v-only-number="{ min: -100, max: 100, precision: 2 }"
    ></el-input>
</template>
<script>
export default {
  name: "HelloWorld",
  directives: {
    onlyNumber: {
      // 只调用一次,第一次绑到元素时调用。在这里可以进行一次性的初始化设置。
      bind: function (el, vDir) {
        let dom = el.tagName == "INPUT" ? el : el.querySelector("input");
        dom.placeholder = "请输入数值" + JSON.stringify(vDir.value);
      },
      // 当被绑定的元素插入到 DOM 中时
      inserted: function (el, vDir) {
        let dom = el.tagName == "INPUT" ? el : el.querySelector("input");
        //记录当前值
        let content = dom.value;
        //插槽参数
        let config = vDir.value;

        /**
         * @function 输入有效值监听事件
         * @description 只允许输入 数字/小数点/负号
         */
        el.addEventListener("keypress", (e) => {
          //阻止输入
          function preventInput() {
            if (e.preventDefault) {
              e.preventDefault();
            } else {
              e.returnValue = false;
            }
          }
          let re = /\d|\.|-/; //只允许输入 数字/小数点/负号
          let key = e.key; //输入值
          content = e.target.value; //输入值生效前的值
          //配置
          let _precision = 2;
          let _max = 100;
          let _min = -100;
          if (config) {
            _precision = parseInt(config.precision);
            _max = parseFloat(config.max);
            _min = parseFloat(config.min);
          }
          if (!re.test(key)) {
            preventInput();
          } else if ((content.indexOf(".") > 0 || !content) && key == ".") {
            // .不允许出现在第一位,且只允许输入一次

            preventInput();
          } else if ((_min >= 0 || content) && key == "-") {
            // "-"号仅可以出现在第一位,且配置最小值允许出现负值

            preventInput();
          } else if (
            // 精度拦截
            content.split("").reverse().join("").indexOf(".") == _precision
          ) {
            // preventInput();
          }
        });
        el.addEventListener("keyup", (e) => {
          let value = e.target.value; //输入值生效后的值
          //输入非数值,keypress已过滤,此处过滤输入法输入中文情况
          if (isNaN(value) && value !== "-") {
            e.target.value = content;
            return false;
          }

          content = value;
          //精度
          let _precision = 2;
          let _max = 100;
          let _min = -100;
          if (config) {
            _precision = parseInt(config.precision);
            _max = parseFloat(config.max);
            _min = parseFloat(config.min);
          }

          if (value > _max) {
            e.target.value = _max;
            content = _max;
          }
          if (value < _min) {
            e.target.value = _min;
            content = _min;
          }
        });
        el.addEventListener("focusout", (e) => {
          let value = e.target.value;
          //精度
          let _precision = 2;
          if (config) {
            _precision = parseInt(config.precision);
          }
          e.target.value =
            value != "" ? parseFloat(value).toFixed(_precision) : "";

          dom.dispatchEvent(new Event("input"));
        });
      },
    },
  },
  data() {
    return {
      test: "",
    };
  },
  
  watch:{
    test(){
      console.log('watch test',this.test)
    }
  }
};

</script>
上一篇下一篇

猜你喜欢

热点阅读