为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用更严格的限制自定义 `<input>` 元素

如何使用更严格的限制自定义 `<input>` 元素

繁花不似锦 2021-09-30 09:30:24
我有一个 html<input>元素,我只想接受数字并在移动设备上将其识别为数字字段。我还希望吞下无效字符,就像标准type=number吞咽不允许的字符一样。我已经尝试过显而易见的,type=number但它有许多缺点。具体来说,它允许 'e'、'+' 和 '-'(至少在 chrome 中),但这些很容易用一些 JS 修复。真正的问题在于'.' 字符,我希望能够输入浮点数,例如“0.10”、“5.5054”,但不想输入无效的字符串,例如“0.10.1”。我试图通过只允许 1 '.' 来解决这个问题。一次,但这失败了input.value,因为浏览器对它进行了按摩,例如“5”。变为 '5','5..' 变为空(!),并且似乎不可能获得输入中键入的原始字符串值。以上意味着检查现有的 '.' 并采取行动似乎是死胡同......核心问题:有没有办法检查和符合输入?'有没有一种方法可以将输入标记为一个没有后勤包袱的数字type=number?注意:* 我意识到你可以粘贴任何你想要的东西,我认为这种行为是病态的,不应该被输入预防所覆盖。更新澄清一下,我已经尝试过keypress, keydownetc 事件,但它们还不够,因为我想查看当前输入中存在多少个 '. 以选择是否允许另一个。此时input.value已经被浏览器按摩以删除'.'。我想根据当前输入的 '.' 的数量有条件地允许字符。例子HTML(为简洁起见,角度样式绑定)<input type="number" (keydown)="keyDown()">JSfunction keyDown($event: KeyboardEvent) {  const inputField = // obtain reference to input element  const value = inputField.value;  if ( value.indexOf('.') !== -1 && $event.key === '.') { // disallow another . if one is present    // ! input field prunes . so this check isn't sufficient    $event.preventDefault();    return;  }  // This is the crux of the problem e.g.  // type 5. into input field, value === 5  // type 5.. into the input field, value === null  // Since the . char is removed by the input element there's no way to know how many are present!  console.log(value);}概括有没有办法在<input>不使用type=number属性设置的情况下发出信号类型为 number 的信号。即移动设备识别和显示数字键盘等对于一个<input>有type=number没有办法吞下所有不会导致有效数字的键输入在浏览器将字符添加到输入中之前,不会进行 janky 删除 keyup
查看完整描述

3 回答

?
叮当猫咪

TA贡献1776条经验 获得超12个赞

一种稍微不同的方法。它允许数字、只有 1 个句点和退格。所有其余的KeyboardEvent.keys 包括ctrl + v和ctrl + c 都被忽略。但是,如果希望允许它们,您可以这样做。


为了检查字符是否是10数字之一,我使用的是event.key因为它们可以有两个不同的代码:Digits[0-9]和Numpad[0-9]。但是对于句号和退格,我使用的是event.code因为它们只有一个代码。


const input = document.querySelector("#number_input");


const App = {

  isDigit: function(key) {

    const digits = [

      "0",

      "1",

      "2",

      "3",

      "4",

      "5",

      "6",

      "7",

      "8",

      "9"

    ];

    return digits.includes(key);

  },

  isPeriod: function(code) {

    return code === "Period";

  },

  isBackSpace: function(code) {

    return code === "Backspace";

  },

  handleEvent: function(event) {

    const key = event.key;

    const code = event.code;

    const value = input.value;

    if (App.isDigit(key) || App.isPeriod(code) || App.isBackSpace(code)) {

      if (App.isPeriod(code) && value.indexOf(key) !== -1) {

        event.preventDefault();

      }

    } else {

      event.preventDefault();

    }

  }

};


input.onkeydown = App.handleEvent

<input id="number_input" />

一个聪明的黑客

由于您坚持使用数字输入。第一次使用,一个虚拟文本输入,您可以使用 CSS 或 Js 隐藏它并验证其值而不是数字输入。


const input = document.querySelector("#number_input");

const dummyInput = document.querySelector("#dummy_input")

const App = {

  isDigit: function(key) {

    const digits = [

      "0",

      "1",

      "2",

      "3",

      "4",

      "5",

      "6",

      "7",

      "8",

      "9"

    ];

    return digits.includes(key);

  },

  isPeriod: function(code) {

    return code === "Period";

  },

  isBackSpace: function(code) {

    return code === "Backspace";

  },

  handleEvent: function(event) {

    const key = event.key;

    const code = event.code;

    const dummyValue = dummyInput.value;

    if (App.isBackSpace(code)) {

      dummyInput.value = dummyValue.substring(0, dummyValue.length - 1)

    } else {

      if (App.isDigit(key) || App.isPeriod(code)) {

        if (App.isPeriod(code) && dummyValue.indexOf(key) !== -1) {

          event.preventDefault();

        } else {

          dummyInput.value += event.key

        }

      } else {

        event.preventDefault();

      }

    }

  }

};


input.onkeydown = App.handleEvent

<input type="number" id="number_input" />

<input type="text" id="dummy_input" />

更新

所有使用 input[type="number"] 的答案都有问题。您可以通过鼠标滚轮/微调器将输入值更改为负数。要解决此问题,请为输入设置最小值。


<input type="number" min="1" id="number_input" />

您需要监听onchange事件,然后更改虚拟输入的值。


const input = document.querySelector("#number_input");

const dummyInput = document.querySelector("#dummy_input")

const App = {

  isDigit: function(key) {

    const digits = [

      "0",

      "1",

      "2",

      "3",

      "4",

      "5",

      "6",

      "7",

      "8",

      "9"

    ];

    return digits.includes(key);

  },

  isPeriod: function(code) {

    return code === "Period";

  },

  isBackSpace: function(code) {

    return code === "Backspace";

  },

  handleEvent: function(event) {

    const key = event.key;

    const code = event.code;

    const dummyValue = dummyInput.value;

    if (App.isBackSpace(code)) {

      dummyInput.value = dummyValue.substring(0, dummyValue.length - 1)

    } else {

      if (App.isDigit(key) || App.isPeriod(code)) {

        if (App.isPeriod(code) && dummyValue.indexOf(key) !== -1) {

          event.preventDefault();

        } else {

          dummyInput.value += event.key

        }

      } else {

        event.preventDefault();

      }

    }

  },

  handleChange: function(event) {

    dummyInput.value = event.target.value

  }

};


input.onkeydown = App.handleEvent;

input.onchange = App.handleChange;

<input type="number" min="1" id="number_input" />

<input type="text" id="dummy_input" />


查看完整回答
反对 回复 2021-09-30
?
慕斯王

TA贡献1864条经验 获得超2个赞

更新


答案根据需求变化进行更新。


好的,我尝试解决另一个问题,即


根据以下代码粘贴您不能粘贴任何内容,您只能粘贴数字,如果您尝试粘贴字符串,输入框将自动变为空:)


  let special = document.getElementById('inputField');

  special.addEventListener("keypress", function(e) {

  let dot = 46;

  // allowed char: 0-9, .

  let allow_char = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, dot];

  if (allow_char.indexOf(e.which) !== -1) {

    // only 1 dot

    if (e.which == 46 && special.value.indexOf('.') !== -1)

      e.preventDefault();

  } else {

    e.preventDefault();

  }

});


function checkString()

{

  setTimeout(() => {

  var value = document.getElementById("inputField").value;

  value = parseInt(value);

    if(isNaN(value))

      document.getElementById("inputField").value = "";

    }, 100);


}

  <input type="number" id="inputField" onpaste="checkString()"/>


查看完整回答
反对 回复 2021-09-30
  • 3 回答
  • 0 关注
  • 177 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信