Vue.js应用电话号码格式化

7
我是新手Vue.js开发者,正在尝试找到一种方法如何在输入框中格式化电话号码为所需格式。我能在stackoverflow上找到一个使用纯javascript编写的答案,但我不知道如何在Vue中使用正则表达式。
javascript解决方案
document.getElementById('phone').addEventListener('input', function (e) {
  var x = e.target.value.replace(/\D/g, '').match(/(\d{0,3})(\d{0,3})(\d{0,4})/);
  e.target.value = !x[2] ? x[1] : '(' + x[1] + ') ' + x[2] + (x[3] ? '-' + x[3] : '');
});

所以我的问题是如何将它应用在这个输入div上?这样用户只能键入数字,并且当他正在输入数字时,数字会以所需格式显示。
<div contentEditable="true" class="inputDiv"></div>

我希望使用vue.js实现以下示例。

document.getElementById('phone').addEventListener('input', function (e) {
  var x = e.target.value.replace(/\D/g, '').match(/(\d{0,3})(\d{0,3})(\d{0,4})/);
  e.target.value = !x[2] ? x[1] : '(' + x[1] + ') ' + x[2] + (x[3] ? '-' + x[3] : '');
});
<input type="text" id="phone" placeholder="(555) 555-5555"/>

我在尝试寻找一个可能非常简单的答案,但由于我对Vue不熟悉,因此无法找到任何可以帮助我使其正常工作的内容。


我不太明白你想要什么:你想在将输入值发送到后端之前对其应用某种格式吗?你想验证数字是否符合特定格式吗?你想修改输入,以便当用户使用错误格式时,应用程序可以实时更正吗? - Sergeon
抱歉问题之前有些混乱。我已经编辑了问题,希望它提供了所有必要的信息。 - Marek Barta
7个回答

19

你可能需要了解一下Vue的工作原理,并进行一些实践以更好地理解。

他们的文档非常棒,你可以从这里开始 - https://v2.vuejs.org/v2/guide/

对于你的问题,这里有一种利用该框架的方法。

new Vue({
  el: "#app",
  data: {
    value: ''
  },
  methods: {
    acceptNumber() {
        var x = this.value.replace(/\D/g, '').match(/(\d{0,3})(\d{0,3})(\d{0,4})/);
  this.value = !x[2] ? x[1] : '(' + x[1] + ') ' + x[2] + (x[3] ? '-' + x[3] : '');
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <h2>Phone number</h2>
   <input v-model="value" type="text" @input="acceptNumber">
</div>


1
正是我所需要的,你说得对,可能需要一些步骤指导。谢谢! - Marek Barta
只有一个问题,我无法将它附加到<div contentEditable="true">而不是<input>...我需要做什么不同的事情? 只有一个问题,我无法将它附加到<div contentEditable="true">而不是<input>...我需要做什么不同的事情? - Marek Barta
v-model 作用于元素的 value 属性,而在 divv-model 不起作用。请使用 v-bind 使其更具可编辑性。 - Satyam Pathak
@SatyamPathak,你能否看一下这里关于vee-validate的问题:https://stackoverflow.com/questions/59444033/vue-js-bootstrapvue-veevalidate-cannot-validate-datepicker? - Istiaque Ahmed

2

介绍Vue-The-Mask

npm install vue-the-mask

在你的组件中

<template>
    <input v-mask="['(###) ###-####']"/>
</template>

<script>
import {mask} from 'vue-the-mask'
export default{
    name: "myComponent",
    directives:{mask}
}
</script>

这太棒了,有很多用途。 - sMyles

1

我的意见是,想象一下你有一个手机模型,你希望对其应用格式。

 data() {
   return {
     phone_number: null,
   };
 }

你的模板应该长这样:

<template>
  <div>
    <input
      type="tel"
      placeholder="(123) 456-7890"
      class="form-control"
      id="input-phone"
      v-model="phone_number"
      maxlength="16"
      @input="enforcePhoneFormat()"
    />
  </div>
</template>

所以,当输入时,您调用enforcePhoneFormat()方法,该方法使用正则表达式并将输入转换为以下格式 - (123) 345-6789
methods: {    
  enforcePhoneFormat() {
    let x = this.phone_number
      .replace(/\D/g, "")
      .match(/(\d{0,3})(\d{0,3})(\d{0,4})/);

    this.phone_number = !x[2]
      ? x[1]
      : "(" + x[1] + ") " + x[2] + (x[3] ? "-" + x[3] : "");
  }
}

要更改首选格式,您需要更改正则表达式。

1
通常在Vue中,你使用v-model来处理表单。在一个典型的表单中,你可能会在组件中有一个phoneNumber变量,并将它与输入框绑定使用v-model
<template>
  <input name="phone" v-model="phoneNumber" />
</template>

<script>
export default new Vue ({
  data() {
    return {
      phoneNumber: '',
    }
  }
})
</script>

问题在于v-model不允许您在用户键入时动态更改值,因此这对您没有用。

但是,您仍然可以使用v-bind提供值,并使用v-on响应用户输入,而不是绑定v-model。以下代码片段将始终将用户编写的任何内容转换为大写:

<template>
  <input name="phone" :value="phoneNumber" @input="handleUserInput" />
</template>

<script>
export default new Vue ({
  data() {
    return {
      phoneNumber: '',
    }
  },
  methods: {
    handleUserInput(input) {
      this.value = input.toUpperCase();
    }
  }
})
</script>

将格式应用于电话号码比toUpperCase()稍微复杂一些,但思路是相同的:

<template>
  <input name="phone" :value="phoneNumber" @input="handleUserInput" />
</template>

<script>
export default new Vue ({
  data() {
    return {
      phoneNumber: '',
    }
  },
  methods: {
    handleUserInput(input) {
      var replacedInput = e.target.value.replace(/\D/g, '').match(/(\d{0,3})(\d{0,3})(\d{0,4})/);
      this.value = !replacedInput[2] ? replacedInput[1] : '(' + replacedInput[1] + ') ' + replacedInput[2] + (replacedInput[3] ? '-' + replacedInput[3] : '');
    }
  }
})
</script>

0

很遗憾,那并没有帮到我。实际上,我不是在格式化电话号码,而是将其用作易于理解的示例,以代替冗长地描述我具体情况。 - Marek Barta
我该如何使用您提供的第一个链接中的组件获取格式化的号码(国家代码+电话号码)? - Istiaque Ahmed
使用npm安装它,按照使用方式包含它,然后像这样使用: <VuePhoneNumberInput v-model="yourValue" /> 此外,您已列出可用于自定义此组件的属性。 - N. Djokic
@N.Djokic,我如何使用JS编程方式为第一个链接中的组件设置国家代码和电话号码? - Istiaque Ahmed
@N.Djokic,你能否在这里看一下一个与vee-validate相关的问题:https://stackoverflow.com/questions/59444033/vue-js-bootstrapvue-veevalidate-cannot-validate-datepicker? - Istiaque Ahmed

0

对@Satyam Pathak的代码进行轻微修改,以支持动态传递属性名。

<script>
export default new Vue ({
  data() {
    return {
      objectName: {},
    }
  }
})
</script>

methods:{
formatPhoneNumber(propertyName) {
      var x = this.objectName[propertyName]
                  .replace(/\D/g, "")
                  .match(/(\d{0,3})(\d{0,3})(\d{0,4})/);

      this.objectName[propertyName] = !x[2]
        ? x[1] : "(" + x[1] + ") " + x[2] + (x[3] ? "-" + x[3] : "");
    }
}

0
let phone_format = function (number) {
    var x = number.replace(/\D/g, '').match(/(\d{0,3})(\d{0,3})(\d{0,4})/);
    if (number.length < 11) {
        number = !x[2] ? x[1] : '(' + x[1] + ') ' + x[2] + (x[3] ? '-' + x[3]:'');
    }
    return number;
};

你可以使用上面的函数。
我像这样使用。
<div class="position-relative">
    <input v-model="aa" style="opacity:0" />
    <div v-html="phone_format(aa)" style="position:absolute;top:0;left:0;width:100%;pointer-events: none;"></div>
</div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接