Не могу понять, где ошибся - если я ввожу вот такой номер 37533 то идет зависание компонента
[Vue warn]: You may have an infinite update loop in a component render function.
found in
---> <TheMask>
<PhoneInput> at src/components/phone-input.vue
<auth/signin.vue> at src/pages/auth/signin.vue
компонент для ввода телефона
<template>
<div class="phone-flag__wrapper">
<app-phone-country-flag v-if="country" :country="country" class="phone-flag__icon"/>
+
<the-mask
ref="phoneMask"
v-model="innerValue"
:class="classInput"
:mask="mask"
:name="name"
:tokens="plusTokens"
class="phone-flag__input"
type="tel"
@input="onInput"
/>
</div>
</template>
<script>
import PhoneCountry from "./phone-country";
import {parsePhoneNumberFromString} from "libphonenumber-js";
import visitorInfo from "visitor-info";
import {findFirstCountryByCode, getMaskToLibPhoneNumber} from "../phone-countries";
export default {
components: {PhoneCountry},
props: {
value: {
type: String,
},
name: {},
classInput: {
type: String,
default: '',
},
autoDetectCountry: {
type: Boolean,
default: false
},
},
data() {
return {
innerValue: this.value.replace('+', ''),
countryCode: "",
mask: "*############",
defaultMask: "*############",
country: "",
isValid: false,
plusTokens: {
"#": {
pattern: /\d/
},
"*": {
pattern: /\d|\+/
}
}
};
},
computed: {
currentNumber: function () {
const plus = /^\+/.test(this.innerValue) || !this.innerValue ? "" : "+";
const filteredNumberArr = this.innerValue
? this.innerValue.match(/[\d+]/g)
: null;
const filteredNumber = filteredNumberArr
? filteredNumberArr.join("")
: "";
return this.mask === this.defaultMask
? `${plus}${filteredNumber}`
: filteredNumber;
}
},
methods: {
onInput: function (value) {
let filteredValue = value.match(/[\d+]/g);
this.innerValue = filteredValue ? filteredValue.join("") : "";
this.updateMaskData();
this.$nextTick(function () {
setTimeout(this.setFocusToEnd.bind(this), 0);
this.$emit("input", `+${this.countryCode}${value}`);
});
},
setFocusToEnd: function () {
const length = this.$refs.phoneMask.$el.value.length;
this.$refs.phoneMask.$el.focus();
this.$refs.phoneMask.$el.setSelectionRange(length, length);
},
updateMaskData: function () {
let {
visitorCountry,
innerValue,
countryCode,
defaultMask,
autoDetectCountry,
} = this;
let phoneInfo = parsePhoneNumberFromString(this.currentNumber);
if (autoDetectCountry && visitorCountry && !innerValue && !phoneInfo) {
phoneInfo = {country: visitorCountry};
}
if (!phoneInfo && this.currentNumber.length > 2) {
phoneInfo = {country: findFirstCountryByCode(this.currentNumber)};
}
const computedMask = getMaskToLibPhoneNumber(phoneInfo);
const computedCountry = phoneInfo && phoneInfo.country ? phoneInfo.country.toLowerCase() : "";
if (autoDetectCountry && visitorCountry) {
if (!innerValue && computedMask) this.innerValue = computedMask.countryCode;
this.visitorCountry = null;
}
if (computedMask && computedMask.mask) {
this.mask = computedMask.mask;
this.country = computedCountry;
this.countryCode = computedMask.countryCode;
this.isValid = !!phoneInfo && !!phoneInfo.isValid && phoneInfo.isValid();
} else if (countryCode.length > this.currentNumber.length) {
this.mask = defaultMask;
this.country = "";
this.countryCode = "";
this.isValid = false;
}
}
},
beforeMount() {
if (this.autoDetectCountry) {
const visitorCountryInfo = visitorInfo();
this.visitorCountry =
visitorCountryInfo && visitorCountryInfo.country
? visitorCountryInfo.country.alpha2
: "";
}
this.updateMaskData();
},
}
</script>
<style lang="scss" scoped>
.phone {
&-flag {
&__wrapper {
display: flex;
align-items: center;
font-size: 1rem;
line-height: 1.5rem;
}
&__input {
flex: 1;
}
&__icon {
margin: -20px -15px -18px -20px;
transform: scale(0.3);
}
}
}
</style>
и файл с масками номеров
export const countries = [
["Bahrain (البحرين)", "bh", "973", "...-....-...."],
["Bangladesh (বাংলাদেশ)", "bd", "880", "...-..-...-..."],
["Barbados", "bb", "1246", ". ... ...-...."],
["Belarus (Беларусь)", "by", "375", "... .. ...-..-.."],
];
const addCountryCodeToMask = (mask, code) => {
const codeLength = code.length;
let temporaryMask = mask;
for (let i = 0; i < codeLength; i++)
temporaryMask = temporaryMask.replace(/#/, code[i]);
return temporaryMask;
};
export const findFirstCountryByCode = code => {
let filteredCode = code.match(/\d/g).join("");
const filteredCountries = countries.filter(
countryArr => countryArr[2] === filteredCode && countryArr[3]
);
if (!filteredCountries[0]) return ""
let country = filteredCountries[0][1]
return country.toUpperCase();
};
export const findFirstCountryByAlpha2 = alpha2 => {
if (!alpha2) return null;
const filteredCountries = countries.filter(
countryArr => countryArr[1] === alpha2
);
if (!filteredCountries[0]) return null
return {country: filteredCountries[0][1], code: filteredCountries[0][2]};
};
export const getMaskToLibPhoneNumber = libPhoneNumberObj => {
const country = libPhoneNumberObj ? libPhoneNumberObj.country : "";
if (!country) return null;
const filteredCountries = countries.filter(
countryArr => countryArr[1].toUpperCase() === country.toUpperCase()
);
if (!filteredCountries[0]) return null;
let mask = filteredCountries[0][3]
? filteredCountries[0][3].replace(/\./g, "#")
: null;
return {
mask: addCountryCodeToMask(mask, filteredCountries[0][2]),
countryCode: `${filteredCountries[0][2]}`
};
};