Библиотека Inputmask подключается в Vue-проекты как обычный npm-пакет и используется либо через директивы, либо через программное применение к DOM-элементам после монтирования компонента. В современных версиях Vue (Vue 3) предпочтение отдаётся директивному подходу или composable-обёрткам, обеспечивающим реактивное обновление маски.
Базовая установка:
npm install inputmask
После установки доступен импорт:
import Inputmask from "inputmask";
Директивный подход обеспечивает наиболее чистую интеграцию с шаблонами Vue и позволяет автоматически управлять жизненным циклом маски.
Простейшая реализация директивы:
// directives/mask.js
import Inputmask from "inputmask";
export default {
mounted(el, binding) {
Inputmask(binding.value).mask(el);
},
updated(el, binding) {
if (binding.value !== binding.oldValue) {
Inputmask.remove(el);
Inputmask(binding.value).mask(el);
}
},
unmounted(el) {
Inputmask.remove(el);
}
};
Регистрация глобально:
import { createApp } from "vue";
import App from "./App.vue";
import mask from "./directives/mask";
const app = createApp(App);
app.directive("mask", mask);
app.mount("#app");
Использование в шаблоне:
<input v-mask="{ mask: '+7 (999) 999-99-99' }" />
В Vue часто требуется изменять маску в зависимости от состояния формы. Inputmask поддерживает полную пересборку конфигурации.
Ключевая особенность заключается в необходимости пересоздания маски при изменении параметров:
updated(el, binding) {
const changed = JSON.stringify(binding.value) !== JSON.stringify(binding.oldValue);
if (changed) {
Inputmask.remove(el);
Inputmask(binding.value).mask(el);
}
}
Типичный сценарий — переключение страны:
<sel ect v-model="country">
<option value="ru">RU</option>
<option value="us">US</option>
</select>
<input v-mask="maskConfig" />
computed: {
maskConfig() {
return this.country === "ru"
? { mask: "+7 (999) 999-99-99" }
: { mask: "+1 (999) 999-9999" };
}
}
Composition API позволяет более гибко управлять жизненным циклом маски и реактивными зависимостями.
import { ref, watch, onMounted, onBeforeUnmount } fr om "vue";
import Inputmask from "inputmask";
export function useMask(maskOptions, inputRef) {
let im = null;
const applyMask = () => {
if (!inputRef.value) return;
if (im) {
im.remove();
}
im = new Inputmask(maskOptions.value);
im.mask(inputRef.value);
};
onMounted(applyMask);
watch(maskOptions, () => {
applyMask();
}, { deep: true });
onBeforeUnmount(() => {
if (im && inputRef.value) {
im.remove();
}
});
}
Использование:
const input = ref(null);
const maskOptions = ref({
mask: "9999-9999-9999-9999"
});
useMask(maskOptions, input);
<input ref="input" />
Inputmask изменяет отображаемое значение, но Vue должен оставаться источником истины. Для этого требуется синхронизация через события ввода.
mounted(el, binding, vnode) {
const im = Inputmask(binding.value);
im.mask(el);
el.addEventListener("input", () => {
vnode.emit("update:modelValue", el.value);
});
}
В компоненте:
<MyInput v-model="phone" />
Такой подход предотвращает рассинхронизацию между DOM и реактивным состоянием.
В Vue 2 используется аналогичный директивный механизм, но с другими хуками жизненного цикла:
Vue.directive("mask", {
bind(el, binding) {
Inputmask(binding.value).mask(el);
},
update(el, binding) {
Inputmask.remove(el);
Inputmask(binding.value).mask(el);
},
unbind(el) {
Inputmask.remove(el);
}
});
Особенность Vue 2 заключается в том, что bind и
update заменяют mounted и
updated, а управление памятью требует более аккуратного
удаления маски.
Inputmask поддерживает маски с алиасами и регулярными выражениями, что удобно при интеграции в Vue-формы.
Пример email-маски:
{ alias: "email" }
<input v-mask="{ alias: 'email' }" />
Для числовых форматов:
{
alias: "numeric",
groupSeparator: " ",
digits: 2,
digitsOptional: false,
prefix: "$ "
}
Такие конфигурации часто используются в финансовых интерфейсах и административных панелях.
Inputmask предоставляет события, которые можно использовать внутри Vue-компонентов:
mounted(el) {
const im = Inputmask({ mask: "999-999" }).mask(el);
el.inputmask.on("complete", () => {
el.classList.add("is-complete");
});
el.inputmask.on("incomplete", () => {
el.classList.remove("is-complete");
});
}
События позволяют строить сложную логику валидации без участия Vue watchers.
При частой смене компонентов или условном рендеринге необходимо гарантировать удаление маски:
onBeforeUnmount(() => {
if (inputRef.value) {
Inputmask.remove(inputRef.value);
}
});
Игнорирование этого шага приводит к накоплению обработчиков событий и некорректной работе input-элементов при повторном монтировании.
Inputmask работает только в браузере, поэтому при использовании Nuxt или SSR необходимо ограничивать выполнение:
if (typeof window !== "undefined") {
Inputmask({ mask: "9999" }).mask(el);
}
Либо использовать клиентские плагины:
export default defineNuxtPlugin(() => {
if (process.client) {
// регистрация директив
}
});
Vue-логика позволяет формировать маски на основе данных формы:
computed: {
dynamicMask() {
return {
mask: this.isInternational ? "+999 999 999 999" : "999 999 9999"
};
}
}
Такие сценарии используются при адаптивных формах регистрации, где структура ввода зависит от региона или типа пользователя.
Inputmask не является полноценной системой валидации, но может использоваться как первый уровень контроля.
el.addEventListener("blur", () => {
if (!el.inputmask.isComplete()) {
el.setCustomValidity("Некорректный формат");
} else {
el.setCustomValidity("");
}
});
Интеграция с нативной HTML5-валидацией позволяет использовать стандартные механизмы Vue-форм без дополнительных библиотек.
Inputmask поддерживает кастомные определения символов:
{
mask: "aa-9999",
definitions: {
a: {
validator: "[A-Za-z]",
casing: "upper"
}
}
}
В Vue это особенно полезно при работе с кодами продуктов, артикулов и внутренних идентификаторов.
При работе с масками важно учитывать позицию курсора, особенно при автозаполнении:
el.addEventListener("focus", () => {
Inputmask.setValue(el, el.value);
});
Поведение курсора напрямую влияет на UX при вводе телефонных номеров и дат.
Типовая структура Vue-приложения с Inputmask включает:
v-mask для шаблонного примененияuseMask для реактивных сценариевТакая организация обеспечивает предсказуемое поведение ввода и масштабируемость при росте количества форм в приложении.