Vue控制的输入

时间:2019-03-16 10:46:01

标签: javascript vue.js vuejs2

我希望文本输入仅接受数字序列。任何其他字符都应静默忽略。这是我组件的简化版本:

<template>
  <div id="app">
    <input :value="tel" @input="setTel" placeholder="only numbers" />
    <p>{{ tel }}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data: () => ({
    tel: "1234"
  }),

  methods: {
    setTel(v) {
      const val = v.target.value.replace(/[^0-9]/g, "");
      this.tel = val;
      /*this.tel = v.target.value = v.target.value.replace(/[^0-9]/g, "");*/
    }
  }
};
</script>

在React中,有controlled components的概念,但是在Vue中似乎没有什么相似之处。

我发现的解决方法(您可以在注释中看到)是手动修改输入元素的值,但这有点违反了使用Vue的目的。

我也尝试使用v-model,但问题仍然存在。

codesandbox.

6 个答案:

答案 0 :(得分:1)

<template>
  <div id="app">
    <input v-model="tel" v-on:keyup="setTel" placeholder="only numbers" />
    <p>{{ tel }}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data: () => ({
    tel: "1234"
  }),

  methods: {
    setTel(v) {
      const val = v.target.value.replace(/[^0-9]/g, "");
      this.tel = val;
      /*this.tel = v.target.value = v.target.value.replace(/[^0-9]/g, "");*/
    }
  }
};
</script>

我查看了您的沙箱并进行了一些修改,请检查是否满足您的要求,视图现已更新。

答案 1 :(得分:1)

好吧,您可以像在这里所说的每个人一样使用<input type=number...,但是如果您想手动处理,则可以在

之类的处理程序中更改el.target.value。
<template>
  <div id="app">
    <input
      :value="tel"
      @input="setTel"
      placeholder="0"
    />
    <p>{{ tel }}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data: () => ({
    tel: "1234"
  }),

  methods: {
    setTel(v) {
      v.target.value = v.target.value.replace(/[^0-9]/g, "");
      this.tel = v.target.value
      /*this.tel = v.target.value = v.target.value.replace(/[^0-9]/g, "");*/
    }
  }
};
</script>

对于vue在输入中显示文本的部分,是因为当您在替换文本后分配相同的值时,vue不会刷新该特定元素的状态以避免额外的渲染

答案 2 :(得分:1)

您应该处理keyup,而不是处理keydown(这将允许密钥到达输入)。处理程序应调用event.preventDefault()event.stopPropagation()来忽略密钥:

// ignore non-numeric keys
if (!/\d/.test(v.key)) {
  v.preventDefault()
  v.stopPropagation()
  return false
}

输入应允许使用元键(例如允许复制粘贴删除):

// allow all meta keys (including Backspace) to pass through
if (v.metaKey || /(Backspace|Meta)/g.test(v.key)) {
  console.log('ignoring', v.key)
  return
}

此外,此输入应处理input事件,以便过滤复制粘贴的值。

// template
<input v-model="tel" @input="onInput" v-on:keydown="setTel" />

// script
onInput(e) {
  if (e.inputType !== 'insertText' && /[^0-9]/g.test(e.target.value)) {
    const val = e.target.value.replace(/[^0-9]/g, "");
    this.tel = val;
    e.preventDefault()
    e.stopPropagation()
    return false
  }
}

demo

答案 3 :(得分:0)

您可以做几件事:

  • 将输入的类型设置为数字<input type=number。这将阻止用户输入除数字以外的任何字符。这由浏览器处理。
  • 您可以使用v-model并添加一个侦听器@change来检查值并相应地修改模型。您可以在模型上添加number修饰符的节点,以便vue将输入转换为数字`
  • 使用诸如vuelidate
  • 之类的验证框架

答案 4 :(得分:0)

您通过使用“替代方法”在输入上设置值来回答了自己的问题。 如果您希望它像React Controlled Components一样工作,则可以将目标输入的值设置为数据模型中的值,除非它实际上更改了数据模型。通过这种方式,Vue数据模型将成为您唯一的真理来源。

<template>
  <div id="app">
    <input 
      v-bind:value="tel" 
      v-on:input="handleInputTel" 
      placeholder="only numbers" 
    />
    <p>{{ tel }}</p>
  </div>
</template>

<script>
export default {
  name: "App",
  data: () => ({
    tel: "1234"
  }),

  methods: {
    handleInputTel(v) {
      if (validate(v.target.value)) this.tel = v.target.value; 
      else v.target.value = this.tel;
    }
  }
};
</script>

答案 5 :(得分:0)

因为VUE的渲染策略,如果状态和old没有区别,这个输入组件不会重新渲染。但是输入 DOM 发生了变化。 因此,您可以在输入事件上使用 $forceUpdate。

setTel(v) {
      const val = v.target.value.replace(/[^0-9]/g, "");
      this.tel = val;
      this.$forceUpdate();
    }